Mongodb агрегирует неожиданный результат массива - необходимо вернуть объект из $ lookup вместо массива - PullRequest
2 голосов
/ 13 января 2020

Я объединяю две коллекции, но результатом трендов является массив, у каждого элемента всегда есть только один тренд. Как удалить тренд из массива?

Коллекция 'Items':

{
 "itemid" : "370",
 "name" : "A"
},
{
"itemid" : "378",
 "name" : "B"
}

Коллекция 'Trends'

{
 "itemid" : "370",
 "max" : "715705",
},
{
 "itemid" : "378",
 "max" : "35346",
}

Выполненная команда:

db.items.aggregate([
{
    $lookup: {
            from: "trends",
            localField: "itemid",
            foreignField: "itemid",
            as: "trend"
            }
    }
])

Результат:

{
 "itemid" : "370",
 "name" : "A",
 "trend" : [       // unexpected array, the result is always a single 'trend'
        {
          "itemid" : "370",
          "max" : "715705",
        }
    ]
},
...

Ожидаемое значение:

{
 "itemid" : "370",
 "name" : "A",
 "trend" : {      // yeah, without array          
             "itemid" : "370",
             "max" : "715705",                    
            }
},
...

Ответы [ 2 ]

2 голосов
/ 13 января 2020

Вы можете сделать это с $ размоткой этапом конвейера

db.items.aggregate([
{
    $lookup: {
            from: "trends",
            localField: "itemid",
            foreignField: "itemid",
            as: "trend"
            }
    },
    $unwind:"$trend"
])
1 голос
/ 13 января 2020

Это не неожиданный результат, так как $lookup приведет к извлечению всех сопоставленных документов в массив, т.е. trend будет массивом в вашем случае. Это по причине. Предположим, что если вы объединяете collection A с collection B, а документы в collection A могут иметь несколько совпадающих документов в collection B, то все эти документы из collection B извлекаются в массив этого относительного документа collection A в вашем случае trend поле. Здесь, если вы хотите получить объект внутри него, вам нужно выполнить одно из следующих действий: *

db.items.aggregate([
{
    $lookup: {
            from: "trends",
            localField: "itemid",
            foreignField: "itemid",
            as: "trend"
            }
    },
    { $addFields: { trend: {$arrayElemAt : ["$trend", 0] } } } // This stage is going re-write trend field with first object from trend array created by $lookup stage.
])

( или )

db.items.aggregate([
{
    $lookup: {
            from: "trends",
            localField: "itemid",
            foreignField: "itemid",
            as: "trend"
            }
    },
     { $unwind: { path: "$trend", preserveNullAndEmptyArrays: true } } 
])

Примечание: Когда вы используете $ unwind , вы должны быть осторожны, если вам нужно использовать опцию preserveNullAndEmptyArrays, как если бы trend было [] - что означает, что совпадение не найдено в collection B, тогда $unwind собирается удалить все collection A документы с trend :[] в конечном результате агрегации.

...