我实际上是在尝试制作一个mongodb请求,首先在列表中填充过滤器,然后在另一个列表上填充。
说明
我的数据库中有以下对象:
{
"_id": ObjectId("..."),
"title": "MySuperProject",
"files": [
{
"title":"My skiing day !",
"right":[{
"role":"USER",
"access":["read"]
}]
},
{
"title":"My little dog, so cute !",
"right":[{
"role":"OTHER",
"access":["read"]
}]
}
],
"people": [
{
"userName":"borat",
"role":"OTHERONE",
"right":[{
"role":"USER",
"access":["read"]
}]
},
{
"userName":"Thomas",
"role":"OTHER",
"right":[{
"role":"OTHER",
"access":["read"]
}]
}
]
}
我需要什么
我需要将参数传递给我的函数,即当前用户角色。在我的情况下,我通过" USER"作用。
这样,我需要检索这个结果:
{
"_id": ObjectId("..."),
"title": "MySuperProject",
"files": [
{
"title":"My skiing day !",
"right":[{
"role":"USER",
"access":["read"]
}]
}
],
"people": [
{
"userName":"borat",
"role":"OTHER",
"right":[{
"role":"USER",
"access":["read"]
}]
}
]
}
这会减少与我匹配的项目角色上的两个列表。
我有什么
我有一个查询,通过" role"来减少文件列表。属性。
事实是,在我的人员列表中,我有两次角色属性:
我的查询通过匹配遇到的第一个角色(people.role而不是people.right.role)来减少人员结果集。
我的查询如下:
db.t.aggregate([
{
$match: {
"title": projectTitle
}
},
{
$redact: {
$cond: [{
$eq: [role, {
$ifNull: ["$role", role]
}]
}, "$$DESCEND", "$$PRUNE"]
}
},
{
$redact: {
$cond: [{
$gt: [{
$size: {
$ifNull: ["$right", [1]]
}
}, 0]
}, "$$DESCEND", "$$PRUNE"]
}
},
])
总结:我需要查询减少人员和与right.role值匹配的文件列表
答案 0 :(得分:0)
$redact
管道阶段不是最好的工具,因为它不能很好地转换为“不同级别的不同条件” “不同地处理不同的数组”< / em>由于其预期功能的性质。
这里更好的情况是普通的旧数组过滤,已经有一段时间的方法。
最好的选择是来自MongoDB 3.2的$filter
,如果你有:
db.t.aggregate([
{ "$project": {
"title": 1,
"files": {
"$filter": {
"input": "$files",
"as": "file",
"cond": { "$eq": [ "$$file.right.role", "USER" ] }
}
},
"people": {
"$filter": {
"input": "$people",
"as": "person",
"cond": { "$eq": [ "$$person.right.role", "USER" ] }
}
}
}}
])
对于MongoDB 2.6,如果您的数组元素真正“不同”且文档中没有两个相同,那么您可以使用$map
和$setDifference
“模拟”该较新的函数来删除数组中的任何false
结果:
db.t.aggregate([
{ "$project": {
"title": 1,
"files": {
"$setDifference": [
{ "$map": {
"input": "$files",
"as": "file",
"in": {
"$cond": [
{ "$eq": [ "$$file.right.role", "USER" ] },
"$$file",
false
]
}
}},
[false]
]
},
"people": {
"$setDifference": [
{ "$map": {
"input": "$people",
"as": "person",
"in": {
"$cond": [
{ "$eq": [ "$$person.right.role", "USER" ] },
"$$person",
false
]
}
}},
[false]
]
}
}}
])
它是相同的基本条件测试,除了在后一种情况下$map
只返回作为输入提供的每个数组元素的元素。因此,匹配的元素或false
的值将被false
中的“设置比较”移至$setDifference
。
这些都是单个管道阶段操作,因此它们是执行此操作的最快方法。
与往常一样,除非您真的需要这些信息继续进入更多的聚合管道阶段,或者如果确实将数据中的内容减少了“重要”数量,从而为您节省了大量的网络流量,那么它总会更好在客户端对数据库本身进行“过滤”。
这些进程中的任何一个都没有真正的开销,但客户端代码可以说是直截了当的,并且可能从“少”的网络流量中获得的可能会在服务器上的处理成本中丢失。