我正尝试使用mongodb学说对mongodb进行汇总查询。
这是我要查询的文档的简化版本:
{
"_id" : ObjectId("574edf0ece8300c95ae0a1a4"),
"user" : {
"$ref" : "User",
"$id" : ObjectId("574eac76ce8300a251e0a1a4"),
"$db" : "master"
},
"content" : "some text",
"hash" : "f46fe1003204704ce11edb15ff4b0ca3f93232da",
"servicesToPublish" : [
{
"serviceTokenId" : "53931163ce830032106dfa6f",
"status" : "published",
"statusUpdatedAt" : ISODate("2016-06-01T13:12:17.000Z"),
"type" : "text"
}
]
}
这是我正在使用的查询:
$aggregationBuilder
->match()
->field('servicesToPublish.status')->equals(ServiceToPublish::STATUS_PUBLISHED)
->field('user.$id')->in($userIds)
->group()
->field('_id')->expression('$hash')
->field('posts')->push($aggregationBuilder->expr()->ifNull('$servicesToPublish', '[]'))
->field('users')->push('$users')
;
转换为以下mongo查询:
db.message.aggregate([{
"$match": {
"servicesToPublish.status": "published",
"user.$id": {
"$in": [ObjectId("5a733013ce8300b566d15a9b"),...]
}
}
}, {
"$group": {
"_id": "$hash",
"posts": {"$push": "$servicesToPublish"},
"users": {"$push": "$user"}
}
}]);
这是示例结果
{
"_id" : "19a5a9315ba8ac5ffb3779e68b887c805c61d54c",
"posts" : [
[
{
"serviceTokenId" : "5a7abe9cce8300c502f38d6c",
"type" : "text",
"status" : "published",
"statusUpdatedAt" : ISODate("2018-04-17T08:20:02.000Z")
},
{
"serviceTokenId" : "59c14d0ece83008449843d15",
"type" : "other",
"status" : "published",
"statusUpdatedAt" : ISODate("2018-04-17T08:20:04.000Z")
}
],
[
{
"serviceTokenId" : "59c13700ce83005a66843d15",
"type" : "text",
"status" : "published",
"statusUpdatedAt" : ISODate("2018-04-17T06:21:57.000Z")
},
{
"serviceTokenId" : "59c13725ce83005668843d15",
"type" : "other",
"status" : "published",
"statusUpdatedAt" : ISODate("2018-04-17T06:21:59.000Z")
}
]
],
"user" : [
{
"$ref" : "User",
"$id" : ObjectId("5a733013ce8300b566d15aa4"),
"$db" : "master"
},
{
"$ref" : "User",
"$id" : ObjectId("5a7abc2ece83003b6af38d6c"),
"$db" : "master"
}
]
}
我需要保持user
和posts
之间的关联,有没有一种方法可以将用户ID用作发布数组中的键(类似这样的内容:"posts": {"id1":[...], "id2": [...]}
)或将用户ID添加到posts数组的每个元素中,例如{"userId":"...", "serviceTokenId" : "...","type":"...", "status":"...", "statusUpdatedAt":ISODate("...")}
如果没有办法做到这一点,我可以确定posts数组的顺序将与用户的顺序相同吗? (即posts
的第一个元素对应于user
的第一个元素)
答案 0 :(得分:1)
您可以使用新的$addFields阶段将用户添加到帖子中。
在简单的monngodb查询中,它看起来像这样:
db.message.aggregate([
{
"$match": {
"servicesToPublish.status": "published",
"user.$id": {
"$in": [ObjectId("5a733013ce8300b566d15a9b"),...]
}
}
},
{
"$addFields" : { servicesToPublish: { $map: {
input: "$servicesToPublish",
as: "service",
in: { $mergeObjects: [ "$$service", { user: "$user" } ] }
} } }
},
{
"$group": {
"_id": "$hash",
"posts": {"$push": "$servicesToPublish"},
"user": {"$push": "$user"}
}
}
]);
应该给你这样的东西:
{
"_id" : "19a5a9315ba8ac5ffb3779e68b887c805c61d54c",
"posts" : [
[
{
"serviceTokenId" : "5a7abe9cce8300c502f38d6c",
"type" : "text",
"status" : "published",
"statusUpdatedAt" : ISODate("2018-04-17T08:20:02.000Z"),
"user" : {
"$ref" : "User",
"$id" : ObjectId("5a733013ce8300b566d15aa4"),
"$db" : "master"
}
},
{
"serviceTokenId" : "59c14d0ece83008449843d15",
"type" : "other",
"status" : "published",
"statusUpdatedAt" : ISODate("2018-04-17T08:20:04.000Z")
"user" : {
"$ref" : "User",
"$id" : ObjectId("5a733013ce8300b566d15aa4"),
"$db" : "master"
}
}
],
[
{
"serviceTokenId" : "59c13700ce83005a66843d15",
"type" : "text",
"status" : "published",
"statusUpdatedAt" : ISODate("2018-04-17T06:21:57.000Z")
"user" : {
"$ref" : "User",
"$id" : ObjectId("5a7abc2ece83003b6af38d6c"),
"$db" : "master"
}
},
{
"serviceTokenId" : "59c13725ce83005668843d15",
"type" : "other",
"status" : "published",
"statusUpdatedAt" : ISODate("2018-04-17T06:21:59.000Z")
"user" : {
"$ref" : "User",
"$id" : ObjectId("5a7abc2ece83003b6af38d6c"),
"$db" : "master"
}
}
]
],
"user" : [
{
"$ref" : "User",
"$id" : ObjectId("5a733013ce8300b566d15aa4"),
"$db" : "master"
},
{
"$ref" : "User",
"$id" : ObjectId("5a7abc2ece83003b6af38d6c"),
"$db" : "master"
}
]
}
您不能单独获得userId,因为您使用的字段名称中带有$
的DBRefs。尝试像{ $mergeObjects: [ "$$services", { userId: "$user.$id" } ] }
一样使用它会导致错误16410“ FieldPath字段名称可能不以'$'开头”。