我有一个名为Container的集合,其中包含一组名为embeddedMany的嵌入式文档。每个嵌入的文档都引用了几个名为Referenced的其他文档,这些引用存储在名为referenceMany的数组中。该文件看起来像这样。
{
"_id" : ObjectId("5a312337ea5cb32d30005d25"),
"embeddedMany" : [
{
"referencedMany" : [
DBRef("Referenced", ObjectId("5a312337ea5cb32d30005d24"), "myDb"),
DBRef("Referenced", ObjectId("5a312337ea5cb32d30005d23"), "myDb")
]
},
{
"referencedMany" : [
DBRef("Referenced", ObjectId("5a312337ea5cb32d30005d23"), "myDb")
DBRef("Referenced", ObjectId("5a312337ea5cb32d30005d22"), "myDb")
]
},
{
"referencedMany" : [
DBRef("Referenced", ObjectId("5a312337ea5cb32d30005d24"), "myDb")
DBRef("Referenced", ObjectId("5a312337ea5cb32d30005d22"), "myDb")
]
}
],
}
现在我需要查找引用某些文档的所有嵌入式文档。让我们说一下:DBRef("Referenced", ObjectId("5a312337ea5cb32d30005d22"), "myDb")
。
我需要生成的文档如下所示:
{
"_id" : ObjectId("5a312337ea5cb32d30005d25"),
"embeddedMany" : [
{
"referencedMany" : [
DBRef("Referenced", ObjectId("5a312337ea5cb32d30005d23"), "myDb")
DBRef("Referenced", ObjectId("5a312337ea5cb32d30005d22"), "myDb")
]
},
{
"referencedMany" : [
DBRef("Referenced", ObjectId("5a312337ea5cb32d30005d24"), "myDb")
DBRef("Referenced", ObjectId("5a312337ea5cb32d30005d22"), "myDb")
]
}
],
}
我读了this非常相似的问题。所以我想我需要使用聚合并过滤embeddedMany字段。到目前为止,我的聚合看起来像这样:
db.Container.aggregate(
[
{
$match: {
"embeddedMany.referencedMany.$id": ObjectId("5a312337ea5cb32d30005d22")
}
},
{
$project: {
"embeddedMany": {
"$filter": {
"input": "$embeddedMany",
"as": "embedded",
"cond": {
"$eq": [
"$$embedded.referencedMany.$id",
ObjectId("5a312337ea5cb32d30005d22")
]
}
}
}
}
},
]
);
这就是我撞墙的地方。因为MongoDB有outstanding bug阻止我比较$id
表达式中的$eq
。有一些提到使用$objectToArray
作为黑客,但我无法将它们全部拉开。
任何帮助都将受到高度赞赏。
答案 0 :(得分:1)
您可以使用以下$project
阶段来比较dbref ID。
$objectToArray
将DBRef转换为键值对。
下一步是$filter
dbref键值对只包含id键值对。
最后一步是$filter
" embeddedMany"数组通过使用$in
表达式将ObjectId值中的传递与引用的多数用户值进行比较。
{"$project":{"embeddedMany":{
"$filter":{
"input":"$embeddedMany",
"as":"embedded",
"cond":{
"$in":[
ObjectId("5a312337ea5cb32d30005d22"),
{
"$map":{
"input":"$$embedded.referencedMany",
"as":"referenced",
"in":{
"$arrayElemAt":[
{
"$let":{
"vars":{
"id":{
"$filter":{
"input":{"$objectToArray":"$$referenced"},
"as":"r",
"cond":{"$eq":["$$r.k",{"$literal":"$id"}]}
}
}
},
"in":"$$id.v"
}
},
0
]
}
}
}
]
}
}
}
}}
答案 1 :(得分:1)
如果您想要的结果与您提供的示例相似,则无需分解对象,也不必担心引用的错误。只需在管道中的DBRef对象之间进行比较(例如在mongo
shell中完成:
mydbref = DBRef("Referenced", ObjectId("5a312337ea5cb32d30005d22"), "myDb");
db.dbref.aggregate([
{$match:{"embeddedMany.referencedMany":mydbref}},
{"$project":{"embeddedMany":{
"$filter":{
"input":"$embeddedMany",
"cond":{
"$in":[{$literal:mydbref},"$$this.referencedMany"]
}
}
}}}
])
{
"_id" : ObjectId("5a312337ea5cb32d30005d25"),
"embeddedMany" : [
{
"referencedMany" : [
DBRef("Referenced", ObjectId("5a312337ea5cb32d30005d23"), "myDb"),
DBRef("Referenced", ObjectId("5a312337ea5cb32d30005d22"), "myDb")
]
},
{
"referencedMany" : [
DBRef("Referenced", ObjectId("5a312337ea5cb32d30005d24"), "myDb"),
DBRef("Referenced", ObjectId("5a312337ea5cb32d30005d22"), "myDb")
]
}
]
}