MongoDB: Обновление вложенных свойств в документе с вложенным массивом
У меня есть структура, которая выглядит следующим образом:
course: { // course
id,
coursename,
sections: { // has an array of sections
section: {
id,
sectionname
cards: { // each section has an array of cards
card: {
id
cardname
}
}
}
}
}
Теперь мне дали ID карты. Предположим, что card ID - 301. У меня нет сведений о курсе или разделе, в котором хранится карта. У меня есть только идентификатор карты. Я хочу обновить имя карты с "Тест 1" до "Тест 2".
Пожалуйста, предоставьте некоторую информацию о том, как обновить имя карты, указав только идентификатор карты. Также, пожалуйста, предоставьте информацию о том, как я могу получить доступ к одной карте, используя только cardId.
Если я запускаю следующий запрос:
db.course.find( {"sections.cards.id" : ObjectId("5859517447c4286d0f0639ee")},
{"sections.cards.$":1,_id:0})
Весь объект раздела возвращается вместо возврата одной карты. Пожалуйста, предоставьте некоторую информацию о том, как получить доступ к одной карте, используя только cardId.
Пример документа, который у меня есть:
{
"_id" : ObjectId("58595041cfdc46100f92a985"),
"modelType" : "Course",
"name" : "c1",
"sections" : [
{
"id" : ObjectId("5859504dcfdc46100f92a986"),
"name" : "s1",
"cards" : [
{
"id" : ObjectId("58595057cfdc46100f92a987"),
"name" : "card1",
},
{
"id" : ObjectId("5859506ccfdc46100f92a988"),
"name" : "card2"
}
]
}
]
}
Пожалуйста, предоставьте информацию о том, как обновить карту, используя только идентификатор карты.
Предположим, я хочу изменить имя карты. Как мне этого добиться?
1 ответ
Надеюсь, этого ответа достаточно для ваших нужд:
db.collection.aggregate([
{$unwind: "$sections"}, // unwind the array
{$unwind: "$sections.cards"}, // unwind the array
{$match: {"sections.cards.id": ObjectId("5859506ccfdc46100f92a988")}}, // filter
{$project: {_id: 0, id: "$sections.cards.id", name: "$sections.cards.name"}} // cut and clear any property that you don't need
])
какой результат в (я проверил это, используя ваш образец):
{
"name" : "card2",
"id" : ObjectId("5859506ccfdc46100f92a988")
}
Объяснение:
- Прежде всего, вам нужно объединить (найти любую библиотеку, как
mongojs
или жеmongoose
и как это сделать в соответствующем руководстве), - затем раскрутите разделы и карточки внутри.
- После обоих шагов необходимо отфильтровать документы, полученные в результате
unwind
Операция по вашему требованию. В этом случае: какая карта соответствует вашему ID - Очистите любые свойства, которые вам не нужны
- Вернуть результат
Чтобы обновить свойства внутри документа:
Невозможно обновить элемент внутри массива без знания его индекса, поэтому сначала вы должны выяснить его индекс / позицию внутри. Самый простой способ, которым я мог придумать, это использовать for
(поскольку у вас двухуровневый массив, я думаю, что метод mapReduce будет намного сложнее):
// first, find the document, where xxx is the target card ID
db.collection.find({'sections.cards.id': ObjectId("xxx")}, function(err, reply){
// iterates through the documents
for(var z = 0; z < reply.length; z++){
// iterates through the `sections`
for(var y = 0; y < reply[z].sections.length; y++){
// iterates through the `cards`
for(var x = 0; x < reply[z].sections[y].cards.length; x++){
if(reply[z].sections[y].cards[x].id.toString() === "xxx")
{
// do what you want to do the card here
reply[z].sections[y].cards[x].name = "updated name";
}
}
}
// save the updated doc one-by-one,
db.collection.update({_id: reply._id}, reply);
}
});
Лучшее решение
Лучшее решение: у вас такого документа нет. Подход к базе данных без схемы не означает, что вы можете поместить все в документ. Вы должны были рассмотреть функциональность и доступность данных при следующем проектировании схемы документа.
Вы можете рационализировать документы в соответствии с вашими потребностями. В этом случае вы должны разделить course
документ, так как ясно, что card
собственность должна быть независимой коллекцией от course
, Если вы беспокоитесь о том, что вам нужно присоединиться к обеим коллекциям, не беспокойтесь. Начиная с 3.2, mongodb ввел $ lookup для такого рода приложений.
Это не только облегчит вам жизнь, но и ускорит выполнение запросов на монго.