Sorun yaşayan populateve bunu yapmak isteyen biri için:
- basit metin ve hızlı yanıtlarla (baloncuklar) sohbet edin
- Sohbet için 4 veritabanı koleksiyonları:
clients, users, rooms, messasges.
- 3 tür gönderici için aynı mesaj DB yapısı: bot, kullanıcılar ve istemciler
refPathveya dinamik referans
populateile pathve modelseçenekler
- Kullanım
findOneAndReplace/ replaceOneile$exists
- getirilen belge yoksa yeni bir belge oluşturun
BAĞLAM
Hedef
- Veritabanına yeni bir basit metin mesajı kaydedin ve bunu kullanıcı veya müşteri verileriyle doldurun (2 farklı model).
- Veritabanına yeni bir QuickReplies mesajı kaydedin ve bunu kullanıcı veya müşteri verileriyle doldurun.
- Her mesaj kendi gönderen türünü kaydedin:
clients, users&bot .
- Yalnızca gönderene sahip olan
clientsveya usersonun Mongoose Modelleri olan iletileri doldurun. _sender tipi istemci modelleri, clientskullanıcı içindir users.
Mesaj şeması :
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);
ÇÖZÜM
Sunucu tarafı API isteğim
Benim kodum
chatUtils.jsKaydetmek istediğiniz mesajın türünü almak için yardımcı program işlevi ( dosyada):
/**
* 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
};
İletiyi kaydetme isteğini almak için sunucu tarafım (Nodejs kullanarak):
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);
}
});
İPUÇLARI :
Veritabanı için:
- Her mesaj bir belgenin kendisidir.
- Bunun yerine kullanmanın
refPath, biz util kullanmak getSenderModelkullanılır populate(). Bunun nedeni bot. sender.typeOlabilir: usersOnun veritabanı ile, clientsonun veritabanı ile ve botbir veritabanı olmadan. refPathDeğilse, Mongooose hata atmak, gerçek Modeli referansı gerekiyor.
sender._idObjectIdkullanıcılar ve müşteriler nulliçin veya bot için yazılabilir .
API istek mantığı için:
quickReplyMesajı değiştiririz (Mesaj DB'nin yalnızca bir hızlı Yanıt olması gerekir, ancak istediğiniz kadar basit metin mesajı gerekir). Veya findOneAndUpdateyerine kullanıyoruz .replaceOnefindOneAndReplace
- Sorgu işlemini (the
findOneAndUpdate) ve populateişlemi callbackher biri ile gerçekleştiriyoruz. Eğer kullanım eğer bilmiyorsanız bu önemlidir async/await, then(), exec()veya callback(err, document). Daha fazla bilgi için Populate Doc'a bakın .
- Hızlı yanıt mesajını
overwriteseçenekle ve $setsorgu operatörü olmadan değiştiriyoruz .
- Hızlı cevabı bulamazsak yeni bir tane yaratırız. Bunu Mongoose'a
upsertseçenekle söylemelisin .
- Değiştirilen mesaj veya yeni kaydedilmiş mesaj için yalnızca bir kez doldururuz.
- İle
findOneAndUpdateve için kaydettiğimiz mesaj ne olursa olsun geri aramalara geri dönüyoruz populate().
- Olarak
populatebiz ile özel bir dinamik model referans oluşturmak getSenderModel. Çünkü Gelincik dinamik başvuru kullanabilirsiniz sender.typeiçin botherhangi Gelincik Modeli değildir sahiptir. Biz kullanmak Veritabanı karşısında doldurulmaya ile modelve pathoptins.
Burada ve orada küçük sorunları çözmek için çok zaman harcadım ve umarım bu birilerine yardımcı olur! 😃