Аггрегация из двух коллекций?
Помогите сформировать запрос. Имеются две коллекции со следующими структурами документов
db.xcover
{
"_id" : ObjectId("5b101caddcab7850a4ba32eb"),
"connections" : [
169906699,
125629607
],
...other-fields
}
db.dcover
{
"_id" : 169906699,
"changed" : true,
"time" : false,
...other-fields
}
связь db.dcover._id in db.xcover.connections
И по сути мне требуется следующее, далее псевдокод запроса:
db.dcover.aggregate([
{
$match: {
$or: [{ changed: true }, { time: true }]
}
},
{
$lookup: {
from: 'xcover',
localField: '_id',
pipeline: [
{ $match: { $expr: { $in: ['$_id', '$xcover.connections'] } } },
{ $unwind: '$xcover' }
],
as: 'xcover'
}
}
])
Т.е. я хочу сделать выборку из dcover, где поле changed или time установленны в true и агрегировать с данными из xcover в массиве поля connections которого, имеются соответствующие идентификаторы документов dcover.
Ответы (1 шт):
Не правильный синтаксис у вас. Вы либо используйте:
$lookup:
{
from: <collection to join>,
localField: <field from the input documents>,
foreignField: <field from the documents of the "from" collection>,
as: <output array field>
}
для одиночного сравнения, либо:
$lookup:
{
from: <joined collection>,
let: { <var_1>: <expression>, …, <var_n>: <expression> },
pipeline: [ <pipeline to run on joined collection> ],
as: <output array field>
}
для множественного. Или, если у вас версия 5.0 и выше:
$lookup:
{
from: <foreign collection>,
localField: <field from local collection's documents>,
foreignField: <field from foreign collection's documents>,
let: { <var_1>: <expression>, …, <var_n>: <expression> },
pipeline: [ <pipeline to run> ],
as: <output array field>
}
При этом во втором случае, для доступа к полям из документов объединенной коллекции, их нужно определять в поле let используя "$$variable" синтаксис.
У pipeline нет прямого доступа к объединенным полям документа. Вместо этого определите переменные для объединенных полей документа, используя опцию let, а затем ссылайтесь на переменные в pipeline.
https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/#mongodb-pipeline-pipe.-lookup
В вашем случае будет так(для версии 5.0 и выше):
db.dcover.aggregate([
{
$match: {
$or: [{ changed: true }, { time: true }]
}
},
{
$lookup: {
from: 'xcover',
localField: '_id',
foreignField: 'connections',
as: 'xcover'
}
}
])
db.dcover.aggregate([
{ $match: { $or: [{ changed: true },{ time: true }] } },
{
$lookup: {
from: 'xcover',
let: { gid: '$_id' },
pipeline: [
{ $match: { $expr: { $in: [ '$$gid', '$connections' ] }}}
],
as: 'xcovers'
}
}
])