MongoDB using NOT and AND together

后端 未结 4 650
遇见更好的自我
遇见更好的自我 2021-02-02 10:53

I\'m trying to negate an $and clause with MongoDB and I\'m getting a MongoError: invalid operator: $and message back. Basically what I want to achieve

4条回答
  •  不思量自难忘°
    2021-02-02 11:40

    Not a standard negation that I can see, you would need a $where operator styled query with JavaScript:

    db.collection.find(function(){ 
        return !( this.institution_type == "A" && this.type == "C" ) 
    })
    

    Not the best as that scans a whole collection, but the negation in your logic requires this as you need to test both values.

    Or the essentially equivalent aggregation operation:

    db.collection.aggregate([
        { "$project": {
            "institution_type": 1,
            "type": 1,
            "notmatched": {
                "$not": {
                    "$and": [
                        { "eq": [ "$institution_type", "A" ] },
                        { "eq": [ "$type", "C" ] }
                    ]
                }
            }
        }},
        { "$match": { 
            "notmatched": true
        }}
    ])
    

    Only just realized this was also a valid form by including the negation on the inside:

    db.collection.find({
        "$or": [
            { "institution_type": { "$ne": "A" } }, 
            { "type": { "$ne": "C" }},
        ]
    })
    

    Where that essentially negates the combination of "A" and "C" in the same document just as the other logic does with a wrapping "not" condition.


    Orig

    In MongoDB queries the $and is actually implicit since that is the default comparison of terms in a query. You only need to use $and when you are looking for multiple conditions on the same field.

    But your query is a simple inequality match:

    db.collection.find({
        "institution_type": { "$ne": "bank" },
        "type": { "$ne": "account_type" }
    })
    

    So you use the $ne operator to negate your terms from a match, where as already stated the $and is implicit so both conditions must apply.

    So with sample data:

    { "institution_type" : "bank", "type" : "account_type" }
    { "institution_type" : "school", "type" : "account_type" }
    { "institution_type" : "school", "type" : "account" }
    

    The query only returns the row that does not meet both conditions:

    { "institution_type" : "school", "type" : "account" }
    

    Your comment says you wan "OR" which you do not specify in your query as you are using "AND", so perhaps you are expecting that "OR" is implicit which is the opposite of what I have told you is the case.

    An $or condition needs to be explicitly applied:

    db.collection.find({
        "$or": [
            { "inititution_type": { "$ne": "bank" } },
            { "type": { "$ne": "account_type" } }
        ]
    })
    

    Which is actually double negation and would return all results.

    Perhaps you mean $nor:

    db.data.find({
        "$nor": [
            { "inititution_type": "bank" },
            { "type": "account_type"  }
        ]
    })
    

    But actually that is logically the same as the first query I gave you.

提交回复
热议问题