Mongodb Mongo查找使用$id引用加入集合
我有一个名为post的集合,它引用了另外两个集合:status和formatMongodb Mongo查找使用$id引用加入集合,mongodb,Mongodb,我有一个名为post的集合,它引用了另外两个集合:status和format post: { "_id" : ObjectId("5d7c1c4549c5e277395871ad"), "status" : { "$ref" : "status", "$id" : ObjectId("status123") }, "format" : { "$ref" : "format", "$id" : Obje
post:
{
"_id" : ObjectId("5d7c1c4549c5e277395871ad"),
"status" : {
"$ref" : "status",
"$id" : ObjectId("status123")
},
"format" : {
"$ref" : "format",
"$id" : ObjectId("format123")
}
}
status:
{
"_id" : ObjectId("status123"),
"name" : "Draft"
}
format:
{
"_id" : ObjectId("format123"),
"name" : "Standard"
}
我希望post查询返回以下内容:
post:
{
"_id" : ObjectId("5d7c1c4549c5e277395871ad"),
"status" : {
"_id" : ObjectId("status123"),
"name" : "Draft"
},
"format" : {
"_id" : ObjectId("format123"),
"name" : "Standard"
}
}
我的Mongo查询应该是什么?我是刚使用MongoDB的,非常感谢您的帮助
谢谢,
很遗憾,您不能在字段名中使用
$
。
但如果我们用这个来代替:
var sid1 = new ObjectId();
var fid1 = new ObjectId();
var postdoc =
{
"_id" : ObjectId("5d7c1c4549c5e277395871ad"),
"status" : {
"ref" : "status",
"id" : sid1
},
"format" : {
"ref" : "format",
"id" : fid1
}
};
var statusdoc =
{
"_id" : sid1,
"name" : "Draft"
};
var formatdoc =
{
"_id" : fid1,
"name" : "Standard"
};
db.post.insert(postdoc);
db.status.insert(statusdoc);
db.format.insert(formatdoc);
然后这个查询:
db.post.aggregate([
{$lookup: {"from": "status",
localField: "status.id",
foreignField: "_id",
as: "STATUS" }}
,{$lookup: {"from": "format",
localField: "format.id",
foreignField: "_id",
as: "FORMAT" }}
,{$project: {
"status": {$arrayElemAt: [ "$STATUS",0 ] },
"format": {$arrayElemAt: [ "$FORMAT",0 ] }
}}
]);
产生期望的结果:
{
"_id" : ObjectId("5d7c1c4549c5e277395871ad"),
"status" : {
"_id" : ObjectId("5d7c921a32c55e3d729b552f"),
"name" : "Draft"
},
"format" : {
"_id" : ObjectId("5d7c921a32c55e3d729b5530"),
"name" : "Standard"
}
}
回答你的问题
你可以这样做
db.post.aggregate([
{$project :
{ status:
{$arrayElemAt:
[{$objectToArray:"$status"},1]
},
format:
{$arrayElemAt:
[{$objectToArray:"$format"},1]
}}},
{$project:
{status:"$status.v" ,
format:"$format.v"}
},
{$lookup :
{from :"status" ,
localField : "status",
foreignField:"_id" ,
as :"status"}
},
{$lookup:
{from :"format" ,
localField:"format",
foreignField:"_id",
as:"format"}
},
{$unwind :"$status"},
{$unwind:"$format"}
])
结果看起来像
{ "_id" : ObjectId("5d7c1c4549c5e277395871ad"),
"status" : {
"_id" : ObjectId("5d7c4af7c45316e35251a499"),
"name" : "Draft"
},
"format" : {
"_id" : ObjectId("5d7c4b21c45316e35251a49a"),
"name" : "Standard"
}
}
解释
阶段1:使用$objectToArray
将文档转换为数组,我们使用它转换DBref阶段2:使用
$arrayElemAt
和$project
获取链接的“\u id”
阶段3:使用$lookup
连接两个集合阶段4:使用
$unwind
获取内部文档。从输入文档解构数组字段以输出每个元素的文档
I could get the desired output using variables.
var post = db.post.findOne({"_id":ObjectId("5d7c8fb8ba38a9196e5fc195")})
var dbRef = post.status
var status = db[dbRef.$ref].findOne({"_id":(dbRef.$id)})
var dbRef1 = post.format
var format = db[dbRef1.$ref].findOne({"_id":(dbRef1.$id)})
db.post.aggregate({ $project : { "_id" : post._id , "status" : status , "format" : format}})
您可以查看MongoDB数据库引用链接以了解更多信息。
这是对数据库的3次单独往返。为什么要使用
$objectToArray
。。。?在这种情况下有点过分了,不是吗?@HbnKing当我使用$unwind时,我看到我所有的帖子都没有返回,有些帖子在结果中显示了多次。我会把我所有的帖子都退回一次,而且只有一次。我可以删除$unwind吗?这似乎解决了我的问题?@BuzzMoschetti你说$objectToArray是什么意思?你有更好的解决方案吗??是的,昨天贴在下面。警告:我已将状态。$id
和格式。$id
更改为状态.id
和格式.id
我不确定OP是否也不能这样做,但是,在使用聚合运算符和字段路径函数时,字段名中以$
开头的数据设计会遇到问题。请使用$unwind
和{$unwind:{path:$size',preserveNullAndEmptyArrays:true}等选项