#javascript #node.js #mongodb
Вопрос:
Как объединить поле массива всех документов вместе в MongoDB?
Например:
Моя коллекция содержит эти документы:
[
{
_id: 0,
categories: ['a', 'b', 'c'],
},
{
_id: 1,
categories: ['d', 'e', 'f'],
},
{
_id: 2,
categories: ['g', 'h', 'i'],
},
];
И результат должен быть:
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
Комментарии:
1.
data.flatMap
это хорошее место для начала2. Как вы можете видеть, мы не знаем, хотите ли вы использовать JavaScript или решение Mongo
Ответ №1:
Лучший способ сделать это-использовать различные
db.collection.distinct('categories')
Если результаты превышают 16 МБ, то вы можете использовать только $unwind
и $group
в агрегированном виде:
db.collection.aggregate([
{
$unwind: "$categories"
},
{
$group: {
_id: "$categories"
}
}
])
Комментарии:
1. Ваш агрегированный запрос не возвращает желаемый результат: пример
2. вы не можете получить точные выходные данные с конвейером агрегации, потому что он возвращает массив объектов по определению.
3. Да, это верно, но OP ожидает массив строк, а не массив объектов.
4. он не сказал, что я думаю, что он хочет уникальных результатов
Ответ №2:
Вы можете $unwind
и $group
вам это понравится:
db.collection.aggregate([
{
"$unwind": "$categories"
},
{
"$group": {
"_id": null,
"categories": {
"$push": "$categories"
}
}
}
])
Пример здесь
Ответ №3:
const list = [
{
_id: 0,
categories: ["a", "b", "c"],
},
{
_id: 1,
categories: ["d", "e", "f"],
},
{
_id: 2,
categories: ["g", "h", "i"],
},
];
let newList = list.map((item) => [...item.categories]);
let finalList = newList.reduce((a, b) => [...a, ...b]);
сначала создайте новый, содержащий все списки категорий из вашего списка. Затем используйте редуктор, как показано на рисунке, с помощью операторов распространения, чтобы разделить их
Ответ №4:
Если вы спрашиваете о JS, я бы использовал метод сокращения:
const res = [
{
_id: 0,
categories: ['a', 'b', 'c'],
},
{
_id: 1,
categories: ['d', 'e', 'f'],
},
{
_id: 2,
categories: ['g', 'h', 'i'],
},
].reduce((acc, current) => ([...acc, ...current.categories]), [])
console.log(res)
Ответ №5:
Ниже приведены 2 способа сделать это, не удаляя дубликаты, потому что я думаю, что вам нужны все значения.
Запрос (решение JF лучше, чем это, но это альтернативный способ)
(Оба запроса работают, если конечный массив категорий
db.collection.aggregate([
{
"$group": {
"_id": null,
"categories": {
"$push": "$categories"
}
}
},
{
"$project": {
"_id": 0
}
},
{
"$set": {
"categories": {
"$reduce": {
"input": "$categories",
"initialValue": [],
"in": {
"$concatArrays": [
"$value",
"$this"
]
}
}
}
}
}
])
ВОЗВРАТ
[
{
"categories": [
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i"
]
}
]
Запрос 2
(если категории > 16 МБ)
db.collection.aggregate([
{
"$unwind": {
"path": "$categories"
}
},
{
"$unset": [
"_id"
]
}
])
ВОЗВРАТ
[
{
"categories": "a"
},
{
"categories": "b"
},
{
"categories": "c"
},
{
"categories": "d"
},
{
"categories": "e"
},
{
"categories": "f"
},
{
"categories": "g"
},
{
"categories": "h"
},
{
"categories": "i"
}
]