#node.js #mongodb #mongoose #mongodb-query #aggregation-framework
#node.js #mongodb #mongoose #mongodb-запрос #агрегация-фреймворк
Вопрос:
Вот пример моей схемы с некоторыми данными:
client {
menus: [{
sections: [{
items: [{
slug: 'some-thing'
}]
}]
}]
}
И я пытаюсь выбрать его следующим образом:
Schema.findOne({ client._id: id, 'menus.sections.items.slug': 'some-thing' }).select('menus.sections.items.$').exec(function(error, docs){
console.log(docs.menus[0].sections[0].items[0].slug);
});
Конечно, «docs.menus [0].sections [0].items [0].slug» работает только в том случае, если в каждом массиве есть только одна вещь. Как я могу заставить это работать, если в каждом массиве есть несколько элементов, без необходимости перебирать все, чтобы найти его?
Если вам нужна более подробная информация, дайте мне знать.
Комментарии:
1. Итак, ваш вопрос на самом деле заключается в том, что несколько
menus.sections.items.slug
могут соответствовать «чему-то», и вы хотите вернуть их все, а не только один. Или вы имеете в виду что-то другое?2. Нет, пуля уникальна и должна возвращать только одну вещь, но она возвращает все содержимое в родительских массивах… поэтому использование [0] не работает.
3. Ваша цитата «Как я могу заставить это работать, если в каждом массиве есть несколько элементов» Я прошу вас объяснить, что вы имеете в виду, если не соответствует более чем одному элементу, как следует из вашего вопроса.
4. Мой вопрос написан плохо.. Что-то вроде Schema.findOne({client._id: id, ‘меню. _id’: id }).select(‘menus.$’) … вернет массив с одним элементом, т.е.. docs.menus[0] … есть ли способ сделать это, когда вы глубже, чем один массив (массив внутри массива)?
5. По сути, я только хочу, чтобы он возвращал соответствующее меню, раздел, элемент… не все меню, разделы и т.д.
Ответ №1:
Структура агрегации хороша для поиска объектов в глубоко вложенных массивах, где позиционный оператор вас подведет:
Model.aggregate(
[
// Match the "documents" that meet your criteria
{ "$match": {
"menus.sections.items.slug": "some-thing"
}},
// Unwind the arrays to de-normalize as documents
{ "$unwind": "$menus" },
{ "$unwind": "$menus.sections" },
{ "$unwind": "$menus.sections.items" }
// Match only the element(s) that meet the criteria
{ "$match": {
"menus.sections.items.slug": "some-thing"
}}
// Optionally group everything back to the nested array
// One step at a time
{ "$group": {
"_id": "$_id",
"items": { "$push": "$menus.sections.items.slug" }
}},
{ "$group": {
"_id": "$_id",
"sections": {
"$push": { "items": "$items" }
}
}},
{ "$group": {
"_id": "$_id",
"menus": {
"$push": { "sections": "$sections" }
}
}},
],
function(err,results) {
}
)
Также см. Другие операторы агрегирования, например, $first
для сохранения других полей в вашем документе при использовании $group
.