किसी के साथ समस्या है populate
और यह भी करना चाहता है:
- सरल पाठ और त्वरित उत्तर (बुलबुले) के साथ चैट करें
- चैट के लिए 4 डेटाबेस संग्रह:
clients
, users
, rooms
, messasges
।
- 3 प्रकार के प्रेषकों के लिए एक ही संदेश DB संरचना: बॉट, उपयोगकर्ता और ग्राहक
refPath
या गतिशील संदर्भ
populate
के साथ path
औरmodel
विकल्पों के
- उपयोग
findOneAndReplace
/replaceOne
साथ$exists
- यदि नया दस्तावेज़ मौजूद नहीं है तो एक नया दस्तावेज़ बनाएँ
संदर्भ
लक्ष्य
- डेटाबेस के लिए एक नया सरल पाठ संदेश सहेजें और इसे उपयोगकर्ता या ग्राहक डेटा (2 अलग-अलग मॉडल) के साथ आबाद करें।
- डेटाबेस के लिए एक नया क्विक रिप्लेज़ संदेश सहेजें और इसे उपयोगकर्ता या क्लाइंट डेटा के साथ पॉप्युलेट करें।
- प्रत्येक संदेश सहेजें अपनी इस प्रकार:
clients
, users
औरbot
।
- केवल उन्हीं संदेशों को पॉप्युलेट करें जिनके पास प्रेषक है
clients
या users
उसके Mongoose मॉडल के साथ है। _sender टाइप क्लाइंट मॉडल है clients
, उपयोगकर्ता के लिए है users
।
संदेश स्कीमा :
const messageSchema = new Schema({
room: {
type: Schema.Types.ObjectId,
ref: 'rooms',
required: [true, `Room's id`]
},
sender: {
_id: { type: Schema.Types.Mixed },
type: {
type: String,
enum: ['clients', 'users', 'bot'],
required: [true, 'Only 3 options: clients, users or bot.']
}
},
timetoken: {
type: String,
required: [true, 'It has to be a Nanosecond-precision UTC string']
},
data: {
lang: String,
// Format samples on https://docs.chatfuel.com/api/json-api/json-api
type: {
text: String,
quickReplies: [
{
text: String,
// Blocks' ids.
goToBlocks: [String]
}
]
}
}
mongoose.model('messages', messageSchema);
उपाय
मेरा सर्वर साइड एपीआई अनुरोध
मेरा कोड
उपयोगिता फ़ंक्शन ( chatUtils.js
फ़ाइल पर ) उस संदेश का प्रकार प्राप्त करने के लिए जिसे आप सहेजना चाहते हैं:
/**
* We filter what type of message is.
*
* @param {Object} message
* @returns {string} The type of message.
*/
const getMessageType = message => {
const { type } = message.data;
const text = 'text',
quickReplies = 'quickReplies';
if (type.hasOwnProperty(text)) return text;
else if (type.hasOwnProperty(quickReplies)) return quickReplies;
};
/**
* Get the Mongoose's Model of the message's sender. We use
* the sender type to find the Model.
*
* @param {Object} message - The message contains the sender type.
*/
const getSenderModel = message => {
switch (message.sender.type) {
case 'clients':
return 'clients';
case 'users':
return 'users';
default:
return null;
}
};
module.exports = {
getMessageType,
getSenderModel
};
संदेश को सहेजने का अनुरोध प्राप्त करने के लिए मेरा सर्वर पक्ष (नोड्स का उपयोग):
app.post('/api/rooms/:roomId/messages/new', async (req, res) => {
const { roomId } = req.params;
const { sender, timetoken, data } = req.body;
const { uuid, state } = sender;
const { type } = state;
const { lang } = data;
// For more info about message structure, look up Message Schema.
let message = {
room: new ObjectId(roomId),
sender: {
_id: type === 'bot' ? null : new ObjectId(uuid),
type
},
timetoken,
data: {
lang,
type: {}
}
};
// ==========================================
// CONVERT THE MESSAGE
// ==========================================
// Convert the request to be able to save on the database.
switch (getMessageType(req.body)) {
case 'text':
message.data.type.text = data.type.text;
break;
case 'quickReplies':
// Save every quick reply from quickReplies[].
message.data.type.quickReplies = _.map(
data.type.quickReplies,
quickReply => {
const { text, goToBlocks } = quickReply;
return {
text,
goToBlocks
};
}
);
break;
default:
break;
}
// ==========================================
// SAVE THE MESSAGE
// ==========================================
/**
* We save the message on 2 ways:
* - we replace the message type `quickReplies` (if it already exists on database) with the new one.
* - else, we save the new message.
*/
try {
const options = {
// If the quickRepy message is found, we replace the whole document.
overwrite: true,
// If the quickRepy message isn't found, we create it.
upsert: true,
// Update validators validate the update operation against the model's schema.
runValidators: true,
// Return the document already updated.
new: true
};
Message.findOneAndUpdate(
{ room: roomId, 'data.type.quickReplies': { $exists: true } },
message,
options,
async (err, newMessage) => {
if (err) {
throw Error(err);
}
// Populate the new message already saved on the database.
Message.populate(
newMessage,
{
path: 'sender._id',
model: getSenderModel(newMessage)
},
(err, populatedMessage) => {
if (err) {
throw Error(err);
}
res.send(populatedMessage);
}
);
}
);
} catch (err) {
logger.error(
`#API Error on saving a new message on the database of roomId=${roomId}. ${err}`,
{ message: req.body }
);
// Bad Request
res.status(400).send(false);
}
});
युक्तियाँ :
डेटाबेस के लिए:
- हर संदेश एक दस्तावेज ही होता है।
- उपयोग करने के बजाय
refPath
, हम getSenderModel
उस उपयोग का उपयोग करते हैं जिसका उपयोग किया जाता है populate()
। यह बॉट की वजह से है। यह sender.type
हो सकता है: users
अपने डेटाबेस के clients
साथ , अपने डेटाबेस के साथ और डेटाबेस के bot
बिना। refPath
सही मॉडल संदर्भ जरूरत है, अगर नहीं, Mongooose एक त्रुटि फेंक देते हैं।
sender._id
ObjectId
उपयोगकर्ताओं और ग्राहकों के null
लिए या बॉट के लिए टाइप किया जा सकता है ।
एपीआई अनुरोध तर्क के लिए:
- हम
quickReply
संदेश को प्रतिस्थापित करते हैं (संदेश DB के पास केवल एक त्वरित रूप से होना चाहिए, लेकिन आप चाहते हैं कि कई सरल पाठ संदेश)। हम या के findOneAndUpdate
बजाय का उपयोग करें ।replaceOne
findOneAndReplace
- हम क्वेरी ऑपरेशन (
findOneAndUpdate
) और प्रत्येक के populate
साथ ऑपरेशन को निष्पादित करते हैं callback
। यह महत्वपूर्ण है अगर आप यदि उपयोग नहीं जानता है async/await
, then()
, exec()
या callback(err, document)
। अधिक जानकारी के लिए पॉपुलेट डॉक देखें ।
- हम
overwrite
विकल्प के साथ और बिना त्वरित उत्तर संदेश को प्रतिस्थापित करते हैं$set
क्वेरी ऑपरेटर के ।
- यदि हमें त्वरित उत्तर नहीं मिलता है, तो हम एक नया बनाते हैं। आपको इसके साथ Mongoose को बताना होगा
upsert
विकल्प के ।
- हम बदले हुए संदेश या नए सहेजे गए संदेश के लिए केवल एक बार पॉप्युलेट करते हैं।
- हम कॉलबैक पर लौटते हैं, जो भी संदेश हमने
findOneAndUpdate
और उसके लिए सहेजा है populate()
।
- में
populate
, हम के साथ एक कस्टम डायनामिक मॉडल संदर्भ बनाते हैं getSenderModel
। हम Mongoose डायनामिक संदर्भ का उपयोग कर सकते हैं क्योंकि इसके sender.type
लिए bot
कोई Mongoose मॉडल नहीं है। हम एक पॉप्युलेटिंग एक्रॉस डेटाबेस का उपयोग करते हैंmodel
और path
ऑप्टिंस के ।
मैं यहाँ और वहाँ छोटी समस्याओं को हल करने में कई घंटे बिताता हूं और मुझे आशा है कि यह किसी की मदद करेगा! 😃