#javascript #mongodb
Вопрос:
Недавно я начал использовать MongoDB и пытаюсь обновить несколько свойств из документа, но не могу получить ссылку на объект для обновления значения.
Пожалуйста, обратите внимание на следующие данные:
const data = {
weekplanId: 'someid',
days: [
{label: 'Monday', cost: 20, comment: "some comment" },
{label: 'Tuesday', cost: 40, comment: "..." }
]
}
const update = await weekplan.updateOne(
{
_id: new ObjectId(data.weekplanId),
},
{
$set: {
"weekdays.$[i].cost": data.days.$[i].cost,
"weekdays.$[i].comment": data.days.$[i].comment,
"weekdays.$[i].date": new Date(),
"weekdays.$[i].someproperty": "something",
}
},
{
arrayFilters: [
{
"i.label": {
$in: data.days.map(p => p.label),
},
}]
}
);
Как я могу ссылаться на объект массива, чтобы задать значение свойства?
Я знаю data.days.$[i].cost
и data.days.$[i].comment
ошибаюсь, они просто пример того, чего я пытаюсь достичь.
Установка date
и someproperty
работает должным образом, так как значения не зависят от исходных данных.
Я хотел бы попытаться сделать это без использования JS.
Подходят ли для этого arrayFilters вообще? Я был бы признателен за некоторые указания относительно того, куда смотреть.
Заранее спасибо!
###РЕДАКТИРОВАТЬ:
Ожидаемый результат:
"_id": {"someid"},
"weekdays": [
{
"day": "Monday",
"cost": 20,
"comment": "some comment",
"date": 2021-08-01T19:51:45.057Z
"someproperty": "something"
},
{
"day": "Tuesday",
"cost": 40,
"comment": "...",
"date": 2021-08-01T19:51:45.057Z
"someproperty": "something"
},
...
...
...
]
Остальные дни недели (среда, четверг, пятница) останутся нетронутыми в этом обновлении.
Комментарии:
1. Не знаю точно, почему вы хотите это сделать, так как это в основном
x=x
так . однако ответить вам вы не можете с помощью обычных операторов обновления. они не могут получить доступ к существующим значениям документов в рамках операции обновления. в этом случае вы хотите использовать конвейерные обновления: docs.mongodb.com/manual/tutorial/…2. Неясно, что вы пытаетесь сделать, если вы можете уточнить, чего именно вы хотите
3. @TomSlabbaert спасибо, я обязательно посмотрю на это.
4. @Zein Я отредактировал сообщение и добавил ожидаемый результат, надеюсь, теперь он более ясен
Ответ №1:
В этом примере код data.days.$[i].cost
оценивается на стороне клиента до отправки запроса, поэтому любое значение (или его отсутствие), которое имеет, будет присвоено соответствующему полю $set
объекта, когда сервер его получит.
data
Объект не будет отправлен на сервер с запросом, поэтому, даже если бы он мог выполнить поиск по массиву входных значений, входного значения там не было бы.
Для этого необходимо выполнить итерацию массива на стороне клиента и программно построить запрос на обновление. Возможно, что-то вроде:
let labelChar = 105;
let setOps = {};
let filters = {};
data.days.forEach( function(day) {
let char = String.fromCharCode(labelChar );
setOps['weekdays.$[' char '].cost'] = day.cost;
setOps['weekdays.$[' char '].comment'] = day.comment;
setOps['weekdays.$[' char '].date'] = new Date();
setOps['weekdays.$[' char '].someproperty'] = "something";
let filterObj = {};
filterObj[char '.label'] = day.label;
filters.push(filterObj);
});
const update = await weekplan.updateOne(
{
_id: new ObjectId(data.weekplanId),
},
{
$set: setOps
},
{
arrayFilters: filters
}
);
Для предоставленного примера ввода это приведет к обновлению:
.updateOne(
{
_id: new ObjectId(data.weekplanId),
},
{
$set: {
'weekdays.$[i].cost': 20,
'weekdays.$[i].comment': 'some comment',
'weekdays.$[i].date': ISODate(),
'weekdays.$[i].someproperty': 'something',
'weekdays.$[j].cost': 40,
'weekdays.$[j].comment': '...',
'weekdays.$[j].date': ISODate(),
'weekdays.$[j].someproperty': 'something'
}
},
{
arrayFilters: [
{'i.label': 'Monday'},
{'j.label': 'Tuesday'}
]
}
);
Комментарии:
1. Спасибо за ваш ответ. Мое объяснение, вероятно, было недостаточно хорошим, я отредактировал сообщение с ожидаемым результатом. Я знаю, что
data.days.$[i].cost
это совершенно неправильно, я использовал это как пример того, что я хотел (вероятно, плохая идея, чтобы так выразиться). Я просто не знаю, как, например, «захватить» значение «20» и использовать его в операции обновления.2. Это именно то, что делает этот код. Вы должны получить значения из массива на стороне клиента, прежде чем отправлять запрос на сервер, потому что массив недоступен на стороне сервера.