0

I want to bitwise check in my data, but not return data.Rights default param is 1. How do I solve this problem?

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") }
    ] 
 }
)

Here is a document I expect to match:

{ 
    "_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
}
A.kadir olmez
  • 311
  • 9
  • 21

1 Answers1

0

The problem with your logic here is that the JavaScript evaluation of the $where clause does not have the same "abilities" as the MongoDB "native" search with regards to "dot notation".

As such, you need to use JavaScript methods of evaluating "each" array element for the properties you want to use. In order to do this, the best condition to use here is the JavaScript .some() array buit-in. It returns true/false to the condition if "any" of the array elements meets your condition and most importantly the "first" that is found without traversing all array elements.

Which also means ( and I hate to be the bearer of bad news here ) that your logic for the comparison of ObjectId in a "matching pair" does not work here without doing the same.

In a normal case you would use $elemMatch to ensure that both properties where met for a specific array element, but you cannot use a $where clause inside $elemMatch, so all the logic needs to be in 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")) });"}
     ]
})

Given the performance problems of $where ( cannot use an index for it's conditions ) I would strongly suggest you find alternate means of "matching your ACL" here to the "bitwise" method you are using.

Yes, other options might come at a greater storage cost, but the trade-off here is that you will get faster query results with elements you can directly match with an $elemMatch clause.

  • how can şt with elemMatch ? can you write example query? – A.kadir olmez Jun 12 '15 at 11:20
  • @A.kadirolmez Well I cannot if you are using a "bitwise" match, for which is the reason you are using JavaScript to do that part. The documentation linked has clear examples, otherwise well here on this site: http://stackoverflow.com/q/15364920/2313887 with multiple examples. `$elemMatch` means that "all" of the properties contained within need to be in the same element of the array. How you wrote it, the match ( for `_id` ) could be in any array element and not just the same one as the "bitwise" match. How I wrote it, it makes sure that "both" properties are matched in the same element. –  Jun 12 '15 at 11:26
  • thanks, i want to bitwise match but can not find any documentation or sample.I actually want to do simple.just want to make the bitwise control in the Acls.Rights property – A.kadir olmez Jun 12 '15 at 11:33
  • @A.kadirolmez Apart from the example I just gave you as an answer you mean. That works, but as I said it is not efficient. You should consider to **not** use a bitwise match for this purpose. Which is the rest of the statement I have already made. The code as show will solve your problem. The advice given is something you should listen to. But questions about that are best posted as other questions. –  Jun 12 '15 at 11:37