#javascript #node.js #arrays #mongodb #mongoose
Вопрос:
Я использую Мангуста в Node.js серверная часть и мне нужно обновить подмножество элементов массива в документе на основе условия. Раньше я выполнял операции с помощью функции save(), как это:
const channel = await Channel.findById(id);
channel.messages.forEach((i) =>
i._id.toString() === messageId amp;amp; i.views < channel.counter
? i.views
: null
);
await channel.save();
Я хотел бы изменить этот код с помощью findByIdAndUpdate, поскольку это всего лишь приращение, и в моем случае нет необходимости извлекать документ. Есть какие-нибудь предложения о том, как я могу выполнить операцию?
Конечно, channel.messages-это обсуждаемый массив. представления и счетчик имеют номер типа.
РЕДАКТИРОВАТЬ — Пример документа:
{
"_id": {
"$oid": "61546b9c86a9fc19ac643924"
},
"counter": 0,
"name": "#TEST",
"messages": [{
"views": 0,
"_id": {
"$oid": "61546bc386a9fc19ac64392e"
},
"body": "test",
"sentDate": {
"$date": "2021-09-29T13:36:03.092Z"
}
}, {
"views": 0,
"_id": {
"$oid": "61546dc086a9fc19ac643934"
},
"body": "test",
"sentDate": {
"$date": "2021-09-29T13:44:32.382Z"
}
}],
"date": {
"$date": "2021-09-29T13:35:33.011Z"
},
"__v": 2
}
Комментарии:
1. Можете ли вы добавить пример документа?
2. @J. F. да, конечно
Ответ №1:
Вы можете попробовать updateOne
метод, если не хотите получать документ в результате,
- совпадают как поля
id
, так иmessageId
условия - проверьте условие выражения,
$filter
чтобы повторить циклmessages
массива и проверитьmessageId
views
, меньше ли иcounter
, тогда он вернет результат, а$ne
условие проверит, что результат не должен быть пустым $inc
чтобы увеличитьviews
на 1, если запрос совпадает, используя$
позиционный оператор
messageId = mongoose.Types.ObjectId(messageId);
await Channel.updateOne(
{
_id: id,
"messages._id": messageId,
$expr: {
$ne: [
{
$filter: {
input: "$messages",
cond: {
$and: [
{ $eq: ["$this._id", messageId] },
{ $lt: ["$this.views", "$counter"] }
]
}
}
},
[]
]
}
},
{ $inc: { "messages.$.views": 1 } }
)