[SERVER-7597] MaxKey behaves in an unexpected way Created: 08/Nov/12  Updated: 15/May/15  Resolved: 15/May/15

Status: Closed
Project: Core Server
Component/s: JavaScript, Querying
Affects Version/s: 2.2.0
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Alvin Richards (Inactive) Assignee: David Storch
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
Operating System: ALL
Participants:

 Description   

Problem:

MaxKey seems to produce an incorrect match, resulting in returning too many documents.

The explain seems to use the right index, not sure if the evaluation of MaxKey is correct

{
	"cursor" : "BtreeCursor fields_1",
	"isMultiKey" : true,
	"n" : 3,
	"nscannedObjects" : 5,
	"nscanned" : 5,
	"nscannedObjectsAllPlans" : 5,
	"nscannedAllPlans" : 5,
	"scanAndOrder" : false,
	"indexOnly" : false,
	"nYields" : 0,
	"nChunkSkips" : 0,
	"millis" : 0,
	"indexBounds" : {
		"fields" : [
			[
				{
					"key1" : 2
				},
				{
					"key1" : { $maxKey : 1 }
				}
			]
		]
	},
	"server" : "vero:27017"
}

Reproduce:

db.form.drop();
 
db.form.insert({"fields" : [ { "key1" : 2 }, { "key2" : "Worlds" } ] })
db.form.insert({"fields" : [ { "key2" : "!" }, { "key5" : "text" } ] })
db.form.insert({"fields" : [ { "key1" : 1 }, { "key2" : "Hello" } ] })
 
db.form.ensureIndex({fields:1})
 
> db.form.find({"fields": {$elemMatch: { $gte: {key1:2}, $lt: {key1:MaxKey}}}})
{ "_id" : ObjectId("509c19a9b72f2fa3103bd760"), "fields" : [ { "key1" : 2 }, { "key2" : "Worlds" } ] }
{ "_id" : ObjectId("509c19a9b72f2fa3103bd761"), "fields" : [ { "key2" : "!" }, { "key5" : "text" } ] }
{ "_id" : ObjectId("509c19a9b72f2fa3103bd762"), "fields" : [ { "key1" : 1 }, { "key2" : "Hello" } ] }

This should return only a single object

{ "_id" : ObjectId("509c19a9b72f2fa3103bd760"), "fields" : [ { "key1" : 2 }, { "key2" : "Worlds" } ] }



 Comments   
Comment by David Storch [ 15/May/15 ]

This is working as designed. Consider the original repro:

db.form.drop();
db.form.insert({"fields" : [ { "key1" : 2 }, { "key2" : "Worlds" } ] })
db.form.insert({"fields" : [ { "key2" : "!" }, { "key5" : "text" } ] })
db.form.insert({"fields" : [ { "key1" : 1 }, { "key2" : "Hello" } ] })
db.form.ensureIndex({fields:1})
db.form.find({"fields": {$elemMatch: { $gte: {key1:2}, $lt: {key1:MaxKey}}}})

The syntax

{ $gte: {key1:2}, $lt: {key1:MaxKey}}

is asking the query engine whether or not there is an array element in fields that is both greater than or equal to the object literal {key:2} and less than the object literal {key1:MaxKey}.

I believe the intention of this query was not to match against object literals, but rather to query the values of the path "fields.key1". The following version of the query returns a single result as expected:

> db.form.find({"fields": {$elemMatch: {key1: {$gte: 2, $lt: MaxKey}}}})
{ "_id" : ObjectId("5556699bc5fbf4584745afbf"), "fields" : [ { "key1" : 2 }, { "key2" : "Worlds" } ] }

Closing as Works as Designed.

Comment by Alvin Richards (Inactive) [ 08/Nov/12 ]

Also reproduced this way

db.form.find().min({fields:{"key1":2}}).max({fields:{"key1":99999}})
{ "_id" : ObjectId("509c19a9b72f2fa3103bd760"), "fields" : [ { "key1" : 2 }, { "key2" : "Worlds" } ] }
 
db.form.find().min({fields:{"key1":2}}).max({fields:{"key1":MaxKey}})
{ "_id" : ObjectId("509c19a9b72f2fa3103bd760"), "fields" : [ { "key1" : 2 }, { "key2" : "Worlds" } ] }
{ "_id" : ObjectId("509c19a9b72f2fa3103bd761"), "fields" : [ { "key2" : "!" }, { "key5" : "text" } ] }
{ "_id" : ObjectId("509c19a9b72f2fa3103bd762"), "fields" : [ { "key1" : 1 }, { "key2" : "Hello" } ] }

Generated at Thu Feb 08 03:15:00 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.