#arrays #mongodb #aggregation-framework
Вопрос:
У меня есть документ, подобный приведенному ниже, я бы, по сути, хотел создать совокупность элементов в поддокументе.
По сути, каждый документ представляет собой запись о продажах, в которой содержится подробная информация о продажах и дополнительный документ / массив с количеством проданных товаров.
Я хотел бы составить краткое описание всех проданных товаров.
Таким образом, примером коллекции является:
{
non_relevant_1: "ABC",
non_relevant_2: "DEF",
items_array: {
"item_1": 1,
"item_2": 2,
"item_3": 1,
"item_4": 1
}
},
{
non_relevant_1: "HIJ",
non_relevant_2: "KLM",
items_array: {
"item_1": 3,
"item_2": 2,
"item_3": 4
}
}
Затем я хотел бы иметь возможность создать что-то вроде:
{
items_array: {
"item_1": 4,
"item_2": 4,
"item_3": 5,
"item_4": 1
}
}
Заранее большое спасибо.
Ответ №1:
Я думаю, вам нужно изменить свою схему, вы сохраняете данные в ключах. Операторы MongoDB не созданы для того, чтобы иметь неизвестные ключи, например, мы не можем группироваться по неизвестному ключу.Для этого мы делаем такие сложные и медленные вещи, как $objectToArray
.
Кроме того, данные, которые вы хотите получить в качестве результатов, имеют ту же проблему.
Если вы посмотрите на запрос только посередине $unwind
, и $group
он будет нужен, с измененной схемой и запросом данных без данных в ключах.
Я имею в виду вместо
items_array: {
"item_1": 1,
"item_2": 2,
"item_3": 1,
"item_4": 1
}
Ваша коллекция должна быть такой(первая часть запроса делает это, изменяя вашу схему)
items_array: [
{"name" "item_1",
"qty" : 1},
{"name" "item_2",
"qty" : 2},
{"name" "item_3",
"qty" : 1},
{"name" "item_4",
"qty" : 1}
]
Кроме того, результаты должны были содержать только известные ключи.
Может быть, причина, по которой ты застрял, заключается в этом.Вы сделаете все намного проще для себя.
Запрос (запрос работает для вашей схемы, но я сказал вам, что я думаю)
db.collection.aggregate([
{
"$addFields": {
"items_array": {
"$map": {
"input": {
"$map": {
"input": {
"$objectToArray": "$items_array"
},
"as": "m",
"in": [
"$m.k",
"$m.v"
]
}
},
"as": "item",
"in": {
"name": {
"$arrayElemAt": [
"$item",
0
]
},
"qty": {
"$arrayElemAt": [
"$item",
1
]
}
}
}
}
}
},
{
"$unwind": {
"path": "$items_array"
}
},
{
"$group": {
"_id": "$items_array.name",
"total-qty": {
"$sum": "$items_array.qty"
}
}
},
{
"$group": {
"_id": null,
"items_array": {
"$push": {
"$map": {
"input": {
"$map": {
"input": {
"$objectToArray": "$ROOT"
},
"as": "m",
"in": [
"$m.k",
"$m.v"
]
}
},
"as": "i",
"in": {
"$arrayElemAt": [
"$i",
1
]
}
}
}
}
}
},
{
"$project": {
"_id": 0
}
},
{
"$addFields": {
"items_array": {
"$arrayToObject": "$items_array"
}
}
}
])
Комментарии:
1. Хм, я действительно начал задаваться вопросом, не ошиблась ли моя схема, но я вижу причину ее изменения. У меня уже есть несколько готовых документов, поэтому я рассмотрю возможность их изменения.
2. я делал то же самое, потому что в языках программирования так часто добавляют данные по ключам, но в MongoDB это значительно усложняет задачу.