#mongodb #aggregation-framework
#mongodb #агрегация-фреймворк
Вопрос:
db.test.insert([
{ name: 'one', refs: [ObjectId('111'), ObjectId('222'), ObjectId('333')] },
{ name: 'two', refs: [ObjectId('222'), ObjectId('333')] },
{ name: 'three', refs: [ObjectId('222'), ObjectId('333'), ObjectId('111')] },
])
В идеале я не хочу группировать документы, если у них одинаковые ссылки (и одинаковое количество ссылок), не имеет значения, в каком порядке они хранятся внутри поля массива. Вот так
[
{
names: ['one', 'three'],
},
{
names: ['two'],
}
]
Насколько я понимаю, мне нужно:
- Сортировать
refs
элементы - Преобразовать
ObjectId
s в строку - Объединить все строки идентификаторов в одну строку и сохранить в определенном поле
- Группировать по этому полю
Пожалуйста, обратите внимание, что реальные документы достаточно велики (скажем, содержат какое-то тяжелое поле «данные», refs
само по себе может содержать в среднем 0-10 элементов, максимум 50), а отфильтрованный ввод может содержать тысячи документов.
Будет ли это наиболее эффективным способом с точки зрения производительности (CPU RAM)?
Обновить
Извините, что не упомянул о важной детали: существуют другие поля, не входящие в массив, которые должны участвовать в группировке. Например
{
name: 'can',
color: 'green',
refs: [ObjectId(1), ObjectId(2)],
material: 'plastic',
price: 50,
}
скажем, мне нужно сгруппировать их по color
refs
material
Ответ №1:
Вы можете использовать один $group
с $setUnion
:
db.test.aggregate([
{ $group: { _id: { $setUnion: "$refs" }, names: { $push: "$name" } } },
{ $unset: "_id" }
])
Если у вас есть еще поля для группировки, просто добавьте их в _id
:
{ $group: {
_id: {
refs: { $setUnion: "$refs" },
color: "$color",
material: "$material"
},
names: { $push: "$name" }
} },
Комментарии:
1. Привет @Wernfried Domscheit, извините, в моем примере не хватало важной детали. Не могли бы вы взглянуть на это?