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

AND of (indexed expression) with (OR containing TEXT) returns incorrect results

    • Type: Icon: Bug Bug
    • Resolution: Done
    • Priority: Icon: Major - P3 Major - P3
    • 2.6.0-rc2
    • Affects Version/s: 2.6.0-rc0
    • Component/s: Querying
    • ALL

      > db.test.ensureIndex({num:1})
      WriteResult({ "nInserted" : 1 })
      > db.test.ensureIndex({words:"text"})
      WriteResult({ "nInserted" : 1 })
      > db.test.insert({_id:1, num: 0})
      WriteResult({ "nInserted" : 1 })
      > db.test.insert({_id:2, num: 0, words:"foo"})
      WriteResult({ "nInserted" : 1 })
      > db.test.find({num:0, $or:[{_id:2}, {$text:{$search:"foo"}}]})
      { "_id" : 1, "num" : 0 } // wrong! this doc doesn't match either clause of the $or.
      { "_id" : 2, "num" : 0, "words" : "foo" }
      > db.test.find({num:0, $or:[{_id:2}, {$text:{$search:"foo"}}]}).explain(true)
      {
      	"cursor" : "BtreeCursor num_1", // invalid plan! queries with TEXT must choose text index plan.
      	"isMultiKey" : false,
      	"n" : 2,
      	"nscannedObjects" : 2,
      	"nscanned" : 2,
      	"nscannedObjectsAllPlans" : 4,
      	"nscannedAllPlans" : 6,
      	"scanAndOrder" : false,
      	"indexOnly" : false,
      	"nYields" : 0,
      	"nChunkSkips" : 0,
      	"millis" : 2,
      	"indexBounds" : {
      		"num" : [
      			[
      				0,
      				0
      			]
      		]
      	},
      	"allPlans" : [
      		{
      			"cursor" : "BtreeCursor num_1",
      			"isMultiKey" : false,
      			"n" : 2,
      			"nscannedObjects" : 2,
      			"nscanned" : 2,
      			"scanAndOrder" : false,
      			"indexOnly" : false,
      			"nChunkSkips" : 0,
      			"indexBounds" : {
      				"num" : [
      					[
      						0,
      						0
      					]
      				]
      			}
      		},
      		{
      			"clauses" : [
      				{
      					"cursor" : "TextCursor",
      					"n" : 0,
      					"nscannedObjects" : 1,
      					"nscanned" : 1,
      					"scanAndOrder" : false,
      					"nChunkSkips" : 0
      				},
      				{
      					"cursor" : "BtreeCursor _id_",
      					"isMultiKey" : false,
      					"n" : 0,
      					"nscannedObjects" : 0,
      					"nscanned" : 0,
      					"scanAndOrder" : false,
      					"indexOnly" : true,
      					"nChunkSkips" : 0,
      					"indexBounds" : {
      						"_id" : [
      							[
      								2,
      								2
      							]
      						]
      					}
      				}
      			],
      			"cursor" : "QueryOptimizerCursor", // the correct plan!
      			"n" : 0,
      			"nscannedObjects" : 1,
      			"nscanned" : 1,
      			"scanAndOrder" : false,
      			"nChunkSkips" : 0
      		},
      		{
      			"cursor" : "Complex Plan",
      			"n" : 0,
      			"nscannedObjects" : 1,
      			"nscanned" : 3,
      			"nChunkSkips" : 0
      		}
      	],
      	"server" : "Rassi-MacBook-Pro.local:27017",
      	"filterSet" : false,
      	"stats" : {
      		"type" : "KEEP_MUTATIONS",
      		"works" : 4,
      		"yields" : 0,
      		"unyields" : 0,
      		"invalidates" : 0,
      		"advanced" : 2,
      		"needTime" : 0,
      		"needFetch" : 0,
      		"isEOF" : 1,
      		"children" : [
      			{
      				"type" : "FETCH",
      				"works" : 3,
      				"yields" : 0,
      				"unyields" : 0,
      				"invalidates" : 0,
      				"advanced" : 2,
      				"needTime" : 0,
      				"needFetch" : 0,
      				"isEOF" : 1,
      				"alreadyHasObj" : 0,
      				"forcedFetches" : 0,
      				"matchTested" : 2,
      				"children" : [
      					{
      						"type" : "IXSCAN",
      						"works" : 2,
      						"yields" : 0,
      						"unyields" : 0,
      						"invalidates" : 0,
      						"advanced" : 2,
      						"needTime" : 0,
      						"needFetch" : 0,
      						"isEOF" : 1,
      						"keyPattern" : "{ num: 1.0 }",
      						"boundsVerbose" : "field #0['num']: [0.0, 0.0]",
      						"isMultiKey" : 0,
      						"yieldMovedCursor" : 0,
      						"dupsTested" : 0,
      						"dupsDropped" : 0,
      						"seenInvalidated" : 0,
      						"matchTested" : 0,
      						"keysExamined" : 2,
      						"children" : [ ]
      					}
      				]
      			}
      		]
      	}
      }
      

      Original description:

      With the following query, the last assertion failed.

      assert: [[ 1, 2, 3, 4, 5, 6 ]] != [[ 2, 3, 4, 5 ]] are not equal : undefined
      
      function expectedIds(cursor, expectedIds) {
        var results = cursor.toArray()
        var ids = results.map(function(result){ return result._id; });
        assert.eq(ids.sort(), expectedIds);
      }
      
      db.test.drop()
      db.test.insert({ _id: 1, words: "dog", num: 3 })
      db.test.insert({ _id: 2, words: "dog cat", num: 3})
      db.test.insert({ _id: 3, words: "dog cat cat", num: 1, loc: [ 20, 20 ] })
      db.test.insert({ _id: 4, words: "dog cat cat", num: 2, loc: [ 40, 40 ] })
      db.test.insert({ _id: 5, words: "cat", num: 4, array: [ { a: 1, b: 2 }, { a: 1, b: 0 } ] })
      db.test.insert({ _id: 6, words: "gato", num: 5, language: "spanish" })
      
      db.test.dropIndexes();
      db.test.ensureIndex({ words: "text" });
      db.test.ensureIndex({ num: 1 });
      var query_or1 = { $or: [ { $text: { $search: "cat"} }, { num: 2 }] }; // [2, 3, 4, 5]
      var query_or2 = { $or: [ { _id: { $gt: 4 } }, { num: { $lt: 4 } } ]}; // [1, 2, 3, 4, 5, 6]
      var query_and = { $and: [ query_or1, query_or2 ]};
      expectedIds(db.test.find(query_or1), [2, 3, 4, 5]);
      expectedIds(db.test.find(query_or2), [1, 2, 3, 4, 5, 6]);
      expectedIds(db.test.find(query_and), [2, 3, 4, 5]);
      

            Assignee:
            david.storch@mongodb.com David Storch
            Reporter:
            siyuan.zhou@mongodb.com Siyuan Zhou
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: