我想按位检查我的数据,但不返回data.Rights默认参数是1.如何解决这个问题?
db.getCollection('forms').find(
{
"IsActive" : true,
"$or" :
[
{ "$where" : "(this.Acls.Rights & 1) == 1" , "Acls.Actor._id" : ObjectId("5565f392a6df191eb4689bec") },
{ "$where" : "(this.Acls.Rights & 1) == 1" , "Acls.Actor._id" : ObjectId("5565f392a6df191eb4689bed") }
]
}
)
这是我希望匹配的文件:
{
"_id" : ObjectId("55686c44a6df1a1008c0b148"),
"IsActive" : true,
"Acls" : [
{
"_id" : ObjectId("557820b1a6df1a032c2c643a"),
"IsActive" : true,
"Actor" : {
"_id" : ObjectId("5565f392a6df191eb4689bec"),
"IsActive" : true,
"Name" : "admin",
"TypeId" : 2
},
"Department" : null,
"Rights" : NumberLong(1)
}
],
"AclCount" : 1
}
答案 0 :(得分:0)
您的逻辑问题在于$where
子句的JavaScript评估与MongoDB“本机”搜索的"dot notation"具有相同的“能力”。
因此,您需要使用JavaScript方法来评估要使用的属性的“每个”数组元素。为了做到这一点,这里使用的最佳条件是JavaScript .some()
数组buit-in。如果“任意”数组元素符合您的条件,则返回true/false
条件,最重要的是在没有遍历所有数组元素的情况下找到的“第一个”。
这也意味着(我不想在这里成为坏消息的承载者),你在“匹配对”中比较ObjectId
的逻辑在这里不起作用。
在正常情况下,您将使用$elemMatch
来确保满足特定数组元素的两个属性,但不能在$where
内使用$elemMatch
子句,因此所有逻辑需要使用JavaScript:
db.forms.find({
"IsActive": true,
"$or": [
{ "$where": "return this.Acls.some(function(el) { return ( el.Rights & 1 == 1 ) && el.Actor._id.equals(ObjectId("5565f392a6df191eb4689bec")) });"}
{ "$where": "return this.Acls.some(function(el) { return ( el.Rights & 1 == 1 ) && el.Actor._id.equals(ObjectId("5565f392a6df191eb4689bed")) });"}
]
})
考虑到$where
的性能问题(不能对其条件使用索引),我强烈建议您在此处找到“匹配ACL”的替代方法,以使用您正在使用的“按位”方法。
是的,其他选项可能会带来更高的存储成本,但这里的权衡是,您可以使用可以直接与$elemMatch
子句匹配的元素获得更快的查询结果。