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

Allow $not to be applied to $regex (currently only /regex/ syntax is allowed)

    • Type: Icon: Improvement Improvement
    • Resolution: Done
    • Priority: Icon: Major - P3 Major - P3
    • 4.0.7, 4.1.8
    • Affects Version/s: 2.4.10, 2.6.0
    • Component/s: Querying
    • Labels:
      None
    • Fully Compatible
    • v4.0
    • Query 2019-02-11

      Executing the following queries I was expecting the same result but apparently they are dealt differently:

      2 scenarios

      • matching
        nair(mongod-2.7.0-pre-) test> db.system.namespaces.find({ name:/\$/} )
        {
          "name": "test.data.$_id_"
        }
        {
          "name": "test.difference.$_id_"
        }
        {
          "name": "test.posts.$_id_"
        }
        {
          "name": "test.kunal.$_id_"
        }
        {
          "name": "test.maha_example.$_id_"
        }
        

        has the same result has using $regex operator

        nair(mongod-2.7.0-pre-) test> db.system.namespaces.find({ name:{ $regex: "\\$"}} )
        {
          "name": "test.data.$_id_"
        }
        {
          "name": "test.difference.$_id_"
        }
        {
          "name": "test.posts.$_id_"
        }
        {
          "name": "test.kunal.$_id_"
        }
        {
          "name": "test.maha_example.$_id_"
        }
        
      • not matching query
        nair(mongod-2.7.0-pre-) test> db.system.namespaces.find({ name: {$not: /\$/}} )
        {
          "name": "test.system.indexes"
        }
        {
          "name": "test.data"
        }
        {
          "name": "test.difference"
        }
        {
          "name": "test.posts"
        }
        {
          "name": "test.kunal"
        }
        {
          "name": "test.maha_example"
        }
        {
          "name": "test.system.profile",
          "options": {
            "capped": true,
            "size": 1048576
          }
        }
        

        But using $regex operator fails

        nair(mongod-2.7.0-pre-) test> db.system.namespaces.find({ name: {$not:  { $regex: "\\$"}}} )
        error: {
          "$err": "Can't canonicalize query: BadValue $not cannot have a regex",
          "code": 17287
        }
        

      Is this the expected behaviour ? and if so why ?

      Looking deeper in the code I can also see the following comment:
      mongo/db/matcher/expression_parser_tree.cpp:103

      ...
               // TODO: this seems arbitrary?
               // tested in jstests/not2.js
               for ( unsigned i = 0; i < theAnd->numChildren(); i++ )
                   if ( theAnd->getChild(i)->matchType() == MatchExpression::REGEX )
                       return StatusWithMatchExpression( ErrorCodes::BadValue, "$not cannot have a regex" );
      ...
      

      and looking int the jstests it makes even less sense:

      jstests/core/not2.js

        49 check( {i:{$not:/a/}}, "b" );
        50 check( {i:{$not:/(a|b)/}}, "", 0 );
        51 check( {i:{$not:/a/,$regex:"a"}}, "", 0 );
        52 check( {i:{$not:/aa/}}, "a", 2 );
        53 fail( {i:{$not:{$regex:"a"}}} );
        54 fail( {i:{$not:{$options:"a"}}} );
      

            Assignee:
            james.wahlin@mongodb.com James Wahlin
            Reporter:
            norberto.leite Norberto Fernando Rocha Leite (Inactive)
            Votes:
            8 Vote for this issue
            Watchers:
            45 Start watching this issue

              Created:
              Updated:
              Resolved: