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)

    XMLWordPrintable

    Details

    • Type: Improvement
    • Status: Closed
    • Priority: Major - P3
    • Resolution: Fixed
    • Affects Version/s: 2.4.10, 2.6.0
    • Fix Version/s: 4.0.7, 4.1.8
    • Component/s: Querying
    • Labels:
      None
    • Backwards Compatibility:
      Fully Compatible
    • Backport Requested:
      v4.0
    • Sprint:
      Query 2019-02-11

      Description

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

        Attachments

          Issue Links

            Activity

              People

              • Votes:
                8 Vote for this issue
                Watchers:
                46 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: