2

we have a collection in below format:

{ "_id" : { "a" : 8, "b" : ObjectId("5b23aa9e24826b82a2553ce7") }, "field1" : "value1", "field2" : "value2", "field3" : "value3", "field4" : "value4", }

as per my knowledge, MongoDB creates a default index on _id field. But here in this case I want to know how MongoDB will create index on _id; is it on both _id.a and _id.b field or just on _id.b field? also if I create an additional compound index on (_id.a,field1,field2), will it create an additional overhead? or I need to create and index on only (filed1,filed2) as _id is already indexed field.

Please suggest. Thanks!

asked Jul 17, 2018 at 18:40

1 Answer 1

1

But here in this case I want to know how MongoDB will create index on _id; is it on both _id.a and _id.b field or just on _id.b field?

The index will index the embedded document as a whole; i.e. the entirety of { "a" : 8, "b" : ObjectId(...) }. This is a different index entirely than one that would be built solely on _id.a, _id.b, or a compound index on both fields.

Note that querying on a nested document requires an exact match of the specified document. To illustrate:

> db.embed.insert({ "_id" : { "a" : 1, "b" : 2 } } )
WriteResult({ "nInserted" : 1 })
> db.embed.find( { "_id" : { "b" : 2, "a" : 1 } } )
> 
> db.embed.find( { "_id" : { "a" : 1, "b" : 2 } } )
{ "_id" : { "a" : 1, "b" : 2 } }

If a single query will be filtering on _id.a, field1 and field2 (e.g. db.foo.find( { "_id.a" : 8, "field1" : "value1", "field2" : "value2" }) ) then then I would recommend building a compound index on the three fields, i.e. { "_id.a" : 1, "field1" : 1, "field2" : 1 }.


Update with more info for comment:

The two queries are not functionally equivalent; the 2nd query will only filter on { "_id": {$lt:{"b":5} }, "field1": "value1" }. For example, try the following:

db.foo.insert({ "_id" : { "a" : 1, "b" : 1 } } )
db.foo.insert({ "_id" : { "a" : 2, "b" : 2 } } )
db.foo.insert({ "_id" : { "a" : 2, "b" : 1 } } )
db.foo.insert({ "_id" : { "a" : 1, "b" : 2 } } )
db.foo.find({ 
 "_id.a":{ "$gt" : 1 },
 "_id.b":{ "$lt": 2} 
})
db.foo.find({
 "_id": { "$gt" : { "a": 1 } },
 "_id": { "$lt" : { "b": 2 } } 
})

Note that queries that filter on multiple fields have an implicit logical AND as long as the fields being filtered on are different. The second query will effectively only be filtering on "_id": { "$lt" : { "b": 2 } } as there are two filters on _id. The $and filter would be needed for the logical AND to be used as intended in this query.

That being said, these two queries are asking different things. The first query is filtering on the embedded values "_id.a" and "_id.b":

> db.foo.find({
... "_id.a" : { "$lt" : 2 }
... })
{ "_id" : { "a" : 1, "b" : 1 } }
{ "_id" : { "a" : 1, "b" : 2 } }
>
> db.foo.find({
... "_id.b" : { "$lt" : 2 }
... })
{ "_id" : { "a" : 1, "b" : 1 } }
{ "_id" : { "a" : 2, "b" : 1 } }

Whereas the second query is asking to return documents where _the entire value of id is greater than / less than the value specified. This can return unexpected results:

> db.foo.find({
... "_id": { "$lt" : { "a": 2 } }
... })
{ "_id" : { "a" : 1, "b" : 1 } }
{ "_id" : { "a" : 1, "b" : 2 } }
>
> db.foo.find({
... "_id": { "$lt" : { "b": 2 } }
... })
{ "_id" : { "a" : 1, "b" : 1 } }
{ "_id" : { "a" : 1, "b" : 2 } }
{ "_id" : { "a" : 2, "b" : 1 } }
{ "_id" : { "a" : 2, "b" : 2 } }
> db.foo.find({
... "_id": { "$gt" : { "b": 1 } }
... })
>
answered Jul 18, 2018 at 1:13
2
  • Thanks @Adam Harrison! on similar lines, if I execute queries like: -->db.foo.find({"_id.a":{$gt:1},"_id.b":{$lt:5},"field1" : "value1"}) and -->db.foo.find({"_id":{$gt:{"a" : 1}},"_id":{$lt:{"b":5}},"field1":"value1"}) both these queries gives same output but execution plan seems to be different, Can you please tell what is the difference between these two queries. Commented Jul 18, 2018 at 4:32
  • Good question. I just updated my response above to answer this and provide some examples. Commented Jul 19, 2018 at 0:01

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.