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

field range with $not should properly account for type bracketing (query with $not returns different results after adding an index)

    • Query
    • OS X

      A query $gt:0 matches all numbers greater than 0. Non numbers do not match. $not:{$gt:0} should match the opposite values of $gt:0, which means all numbers <=0 and all non numbers. I believe the matcher implements this behavior, but the FieldRange constructor employs type bracketing and only matches numbers <= 0.

      Here is a test:

      c = db.c;
      c.drop();
      
      c.save( {} );
      
      // Does not match.                                                                             
      printjson( c.find( { a:{ $lt:0 } } ).toArray() );
      printjson( c.find( { a:{ $lt:0 } } ).explain() );
      // Does match.                                                                                 
      printjson( c.find( { a:{ $not:{ $gt:0 } } } ).toArray() );
      printjson( c.find( { a:{ $not:{ $gt:0 } } } ).explain() );
      
      c.ensureIndex( { a:1 } );
      
      // Does not match.                                                                             
      printjson( c.find( { a:{ $lt:0 } } ).toArray() );
      // Includes numbers < 0.                                                                       
      printjson( c.find( { a:{ $lt:0 } } ).explain() );
      // Now does not match.                                                                         
      printjson( c.find( { a:{ $not:{ $gt:0 } } } ).toArray() );
      // Includes numbers < 0.  But should also include non numbers.                                 
      printjson( c.find( { a:{ $not:{ $gt:0 } } } ).explain() );
      

      -------------------------------------------------

      Without an index, a $not $gt query will return docs where the queried field is missing. Adding an index on that field causes the query to return only documents where the field is present. See example below.

      $ ./mongo
      MongoDB shell version: 2.2.0
      connecting to: test
      > db.version()
      2.2.0
      > db.foo.drop();
      true
      > db.foo.insert(

      {name: 'a', data: 1}

      );
      > db.foo.insert(

      {name: 'b'}

      );
      > db.foo.find({data: {$not: {$gt: 2}}});

      { "_id" : ObjectId("506ddd6228c47c8b340cc0a9"), "name" : "a", "data" : 1 } { "_id" : ObjectId("506ddd6228c47c8b340cc0aa"), "name" : "b" }

      > db.foo.ensureIndex(

      {data: 1}

      );
      > db.foo.find({data: {$not: {$gt: 2}}});

      { "_id" : ObjectId("506ddd6228c47c8b340cc0a9"), "name" : "a", "data" : 1 }

      >

            Assignee:
            backlog-server-query Backlog - Query Team (Inactive)
            Reporter:
            jlfaber Joe Faber
            Votes:
            6 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated:
              Resolved: