A
A
Alexander Batalov2012-08-23 23:21:18
MongoDB
Alexander Batalov, 2012-08-23 23:21:18

What is the correct way to search by the key of a nested MongoDB document?

Given:

{
   _id : 1,
   attrib : {
         a : {obj1},
         b : {obj2}
   }
}

Task: check for the existence of objects (a, b).
The method proposed in the manual is slow and does not use indexes:
db.coll.find({'attrib.a' : {$exists : 1} }) // медленно, индексы не используются

db.coll.find({attrib : {a : {$exists : 1}} }) // нигде не предложенный способ, который к тому же не работает ))

db.coll.ensureIndex({attrib : 1}) // Нет эффекта для поиску по индексу
db.coll.ensureIndex({'attrib.a' : 1}) // Нет эффекта для поиску по индексу

How to properly arrange indexes so that the search for the existence of keys (a, b) is fast?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
G
gelas, 2012-08-24
@gelas

directly with $exists: true apparently nothing will work.
But you can try to dodge in several ways:
1. Add a service field, which is indexed. This can also have a good effect on the size of the index, especially if a and b are large, then indexing them entirely for the sake of $exists is wasteful.
2. If a and b are always of the same type, you can try using a query like this db.coll.find({'attrib.a': {'$type': 3}})
At least according to explain, the index he uses.

S
SnakeSolid, 2012-08-24
@SnakeSolid

The essence of the question is not entirely clear, if you mean getting all documents containing attrib.a. Then you can use sparse indexes:

> db.ttt.find(); // документы коллекции
{ "_id" : ObjectId("50377f098537d96af9ea28ae"), "attrib" : { "a" : { }, "b" : { } } }
{ "_id" : ObjectId("50377f0c8537d96af9ea28af"), "attrib" : { "b" : { } } }
{ "_id" : ObjectId("50377f0f8537d96af9ea28b0"), "attrib" : { "a" : { } } }
{ "_id" : ObjectId("50377f138537d96af9ea28b1"), "attrib" : { } }

> db.ttt.ensureIndex({'attrib.a':1}, {sparse : true}); // разряженный индекс
> db.ttt.find().sort({'attrib.a':1}); // в результате будут только документы содержащие attrib.a
{ "_id" : ObjectId("50377f0f8537d96af9ea28b0"), "attrib" : { "a" : { } } }
{ "_id" : ObjectId("50377f098537d96af9ea28ae"), "attrib" : { "a" : { }, "b" : { } } }

> db.ttt.find().hint({'attrib.a':1}); // явно указан индекс
{ "_id" : ObjectId("50377f0f8537d96af9ea28b0"), "attrib" : { "a" : { } } }
{ "_id" : ObjectId("50377f098537d96af9ea28ae"), "attrib" : { "a" : { }, "b" : { } } }

You can immediately select documents with a certain attrib.a value. If you need to check for the presence of objects in a particular document, then this option is most likely not suitable.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question