【问题】
Hi,
i am trying to use mongodb aggregate query using $setUnion, $project and also $group to group the documents. The structure of document is
{
“_id” : ObjectId(“55014006e4b0333c9531043e”),
“acls” : {
“append” : {
“users” : [ObjectId(“54f5bfb0336a15084785c393”) ],
“groups” : [ ]
},
“edit” : {
“groups” : [ ],
“users” : [
ObjectId(“54f5bfb0336a15084785c392”)
]
},
“fullControl” : {
“users” : [ ],
“groups” : [ ]
},
“read” : {
“users” : [ObjectId(“54f5bfb0336a15084785c392”), ObjectId(“54f5bfb0336a15084785c398”)],
“groups” : [ ]
}
},
name: “ABC”
}
{
“_id” : ObjectId(“55014006e4b0333c9531043f”),
“acls” : {
“append” : {
“users” : [ObjectId(“54f5bfb0336a15084785c365”) ],
“groups” : [ ]
},
“edit” : {
“groups” : [ ],
“users” : [
ObjectId(“54f5bfb0336a15084785c392”)
]
},
“fullControl” : {
“users” : [ ],
“groups” : [ ]
},
“read” : {
“users” : [ObjectId(“54f5bfb0336a15084785c392”), ObjectId(“54f5bfb0336a15084785c370”)],
“groups” : [ ]
}
},
name: “ABC”
}
I need to query based on the name, then i need to use $setUnion for “acls.read.users, acls.edit.users, acls.append.users and acls.fullControl.users” and after that i need to group the documents by “name” and another field having the list of users in “user field” like below
{
result : [
{
_id: “ABC”,
readUsers : [
ObjectId(“54f5bfb0336a15084785c393”),
ObjectId(“54f5bfb0336a15084785c392”),
ObjectId(“54f5bfb0336a15084785c398”),
ObjectId(“54f5bfb0336a15084785c365”),
ObjectId(“54f5bfb0336a15084785c370”)
]
}
]
}
The query i tried like below
db.abc.aggregate([
{$match:{“name”:“ABC”}},
{$project:{users : {$setUnion:[“$acls.read.users”,“$acls.edit.users”,“$acls.append.users”,“$acls.fullControl.users”]}}},
{$group: {_id: “$owner”,“readuser”: “$user”}}
])
when i run the query i am getting error like
aggregate failed: {
“errmsg” : “exception: invalid operator ‘$setUnion’”,
“code” : 15999,
“ok” : 0
}
Can anyone tell me is it possiible to get the result like above and how to achieve it?
【回答】
用 Mongodb 本身的 API 需要硬编码才能实现子文档的合并,不够直观且难度较大,这种情况下可以用集算器来实现,代码如下:
A | |
1 | =mongo_open(“mongo://localhost:27017/local?user=test&password=test”) |
2 | =mongo_shell(A1,”test37.find()”) |
3 | =A2.group(name) |
4 | =A3.new(name,~.(acls.read.users|acls.append.users|acls.edit.users|acls.fullControl.users).(~.id()).union():readUser) |
5 | >mongo_close(A1) |
A2:
A3:数据根据 name 分组
A4:每组数据的 acls 列内数据合并成一个序列,作为 readUser 保存