#mongodb
Вопрос:
Предположим, у меня есть коллекция, подобная следующей:
{
name: "A",
age: 50,
children: [
{
name: "B",
age: 40,
children: [
{
name: "C",
age: 30,
children: []
}
]
}
]
},
{
name: "D",
age: 60,
children: []
}
Два разных запроса, которые я хотел бы выполнить.
1) Найдите любого, кто соответствует определенному возрасту. Верните корневого пользователя и всех его вложенных дочерних элементов.
бывший)
Если мы запросим возраст = 40, то он вернет объект A и все его вложенные дочерние элементы.
Если мы запросим возраст = 50, то он вернет объект A и все его вложенные дочерние элементы.
Для этой проблемы одним из решений, о котором я думал, было создание другого поля, называемого коллекцией возраста. Он просто сохранит список всех возрастов внутри, а затем я смогу проиндексировать эту коллекцию. Однако я не хочу вручную поддерживать эту коллекцию, так как это было бы очень подвержено ошибкам. Выполнение этого таким образом означает, что каждый раз, когда добавляется новый человек, мне придется добавлять его в коллекцию, и то же самое касается удаления. Есть ли лучший способ сделать это?
2) Найдите кого — нибудь с определенным именем.
бывший)
Если мы запросим name = «C», то он вернет объект C.
Если мы запросим name = «A», то он вернет объект A и все его вложенные дочерние элементы.
Я не слишком уверен, как решить эту проблему. Я полагаю, что могу создать новую коллекцию, содержащую каждую отдельную запись; что-то вроде
{
name: "A",
age: 50,
children: [
{
name: "B",
age: 40,
children: [
{
name: "C",
age: 30,
children: []
}
]
}
]
},
{
name: "B",
age: 40,
children: [
{
name: "C",
age: 30,
children: []
}
]
},
{
name: "C",
age: 30,
children: []
},
{
name: "D",
age: 60,
children: []
}
Но опять же, я не хочу поддерживать копию вручную, и этот подход будет содержать много дубликатов.
Любые мысли будут оценены по достоинству. Спасибо!
Комментарии:
1. Достаточно ли вы гибки, чтобы изменить структуру данных сбора?
2. Предпочтительно, я надеялся сохранить текущую структуру и выполнить какую-то специальную индексацию, но я не смог найти никакого способа сделать это. Объем данных может быть огромным, и запросы должны быть быстрыми.
Ответ №1:
Один из подходов заключается в использовании проекции в вашем запросе
Вот пример:
Для запроса: Найдите любого, кто соответствует определенному возрасту.
Вы можете добавить поле со списком всех возрастов, чтобы сохранить этот список, вы можете использовать триггер базы данных
Ознакомьтесь с этой документацией по триггеру
Для запроса: Найдите кого-нибудь с определенным именем.
db.collection.find({
name: "A"
},
{
children: 0
})
Ссылка на игровую площадку Mongo для проверки запроса: Игровая площадка Mongo
Предложение:
Лучше просто сохранить ссылку, а не хранить весь документ детей
Коллекция может выглядеть так
[
{
"_id": ObjectId("5a934e000102030405000000"),
"age": 50,
"name": "A",
children: [
"B"
]
},
{
"_id": ObjectId("5a934e000102030405000001"),
"age": 40,
"name": "B",
children: [
"C"
]
},
{
"_id": ObjectId("5a934e000102030405000002"),
"age": 30,
"name": "C",
children: []
},
{
"_id": ObjectId("5a934e000102030405000003"),
"age": 60,
"name": "D",
children: []
}
]
Чтобы найти детей, вы можете использовать $graphLookup
вот так
db.collection.aggregate([
{
$graphLookup: {
from: "collection",
startWith: "$children",
connectFromField: "children",
connectToField: "name",
depthField: "depth",
as: "children"
}
},
{
"$project": {
"children.children": 0
}
}
])
Ссылка на игровую площадку Mongo для проверки запроса: Игровая площадка Mongo
Комментарии:
1. Спасибо за ответ. Извините, если я не был ясен, но для «Найти кого-либо, соответствующего определенному возрасту», он также должен искать детей. Например, если я ищу возраст=30, он должен возвращать C. Предложение «Найти кого-нибудь с определенным именем» выглядит многообещающим. Я еще немного почитаю об этом.
2. Хорошо… есть ли у вас какие-либо ограничения на вложенность? как и у MongoDB docs.mongodb.com/manual/reference/limits/…
3. О, я этого не знал! Но, гнезд будет не так много.
4. Хорошо… Итак, если вы запросите возраст=40 лет, вы хотите только B или B со всеми его детьми?
5. B и все его дети