Агрегация выполняется на сервере базы данных, в то время как ссылки расширяются драйвером на стороне клиента, поэтому значение, которое фактически отображается в конвейере, равно
DBRef("User",ObjectId(...),"DatabaseName")
К которому можно получить доступ, как объект
{"$ref":"User", "$id":ObjectId(...), "$db":"DatabaseName"}
Но возникает еще одна проблема: имена полей не могут начинаться с $
, поэтому это приведет к ошибке:
{$eq:["$$charge.user.$id",mongoose.Types.ObjectId(req.user._id)]}
Так что вы можете пропустить этот шаг в агрегации и верните документ обратно в mon goose для заполнения, или, если сопоставление на $id
- это все, что вам нужно, вы можете использовать $objectToArray
, чтобы разбить DBRef, чтобы вы могли сопоставить:
{$match: {'_id': mongoose.Types.ObjectId(req.query.payment_order_id)}},
{$unwind: "$charges"},
{$addFields: {charges:{$objectToArray:"$charges"}}},
{$match: {charges:{
$elemMatch:{k:"$id",v:mongoose.Types.ObjectId(req.user._id}
}}},
{$group:{_id:"$_id", charges:{$push:{$arrayToObject("$charges"}}}}}
Это возвращает вам DBRef, которые могут быть расширены драйвером, но это соответствует _id
документа charges
, что, вероятно, не то, что вы хотите.
Однако, однажды у вас есть _id
документа об оплате, вы можете использовать $lookup
и затем отфильтровать их, но затем мы также должны иметь дело с user
как DBref:
{$match: {'_id': mongoose.Types.ObjectId(req.query.payment_order_id)}},
{$unwind: "$charges"},
{$addFields: {chargeId:{$filter:{
input:$objectToArray:"$charges"
cond:{$eq:["$$this.k","$id"]}
}}}},
{$lookup:{
from:"charge",
localField:"$chargeId.v",
foreignField:"$_id",
as: charges
}},
{$unwind:"$charges"},
{$addField:{chargeUser:{$filter:{
input:{$objectToArray:"$charges.user"},
cond:{$eq:["$$this.k","$id"]}
}}}},
{$match: {"chargeUser.v":mongoose.Types.ObjectId(req.user._id)}},
{$project:{
chargeUser:0,
chargeId:0
},
{$group:{
_id:"$_id",
document:{$first:"$$ROOT"},
charges:{$push:"$charges"}
}},
{$addFields:{"document.charges":"$charges"}},
{$replaceRoot:{newRoot:"$document"}}