Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-14201

Support $not in document match negation

    XMLWordPrintableJSON

Details

    • Icon: Improvement Improvement
    • Resolution: Done
    • Icon: Minor - P4 Minor - P4
    • None
    • None
    • Index Maintenance, Querying
    • None

    Description

      Given the example of a set of documents like this:

      { "status" : "A", "type" : "C" }
      { "status" : "A", "type" : "D" }
      { "status" : "B", "type" : "C" }
      { "status" : "B", "type" : "D" }
       

      Currently if you wanted to find all documents that did not contain the combination of "status": "A" and "type": "C" you would have to resort to JavaScript evaluation.

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

      The aggregation pipeline allows such casting to a projection of a field:

       
          db.collection.aggregate([
              { "$project": {
                  "status": 1,
                  "type": 1,
                  "unmatched": {
                      "$not": {
                          "$and": [
                              { "$eq": [ "$status", "A" ] },
                              { "$eq": [ "$type", "C" ] }
                          ]
                      }
                  }
              }},
              { "$match": {
                  "unmatched": false
              }}
          ])
      {code:javascript}
       
      But as there is not a native form of this for a query you could not filter for a $match stage.
       
      The seemingly natural form would be the similar:
       
      {code: javascript}
       
          db.collection.find({ "$not": { "status": "A", "type": "C" } })
       

      Where the existing $not operator applied it's left side evaluation to the query match negating the whole expression of the query on the right side.

      Not sure if there is an efficient way to apply this to index values or whether the result would be the same collection scan for all documents not matching the exclusion.

      The general problem presently being that $not is not allowed as a top level operator here at the moment and cannot reverse the entire query condition as it expects a left side field value. And the JavaScript form for a $where clause is not allowed within an aggregation expression

      error: {
              "$err" : "Can't canonicalize query: BadValue unknown top level operator: $not",
              "code" : 17287
      }

      Attachments

        Activity

          People

            Unassigned Unassigned
            neillunn Neil Lunn
            Votes:
            0 Vote for this issue
            Watchers:
            7 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: