Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB - Query on nested field with index

Tags:

mongodb

I am trying to figure out how I must structure queries such that they will hit my index. I have documents structured like so:

{ "attributes" : { "make" : "Subaru", "color" : "Red" } }

With an index of: db.stuff.ensureIndex({"attributes.make":1})

What I've found is that querying using dot notation hits the index while querying with a document does not.

Example:

db.stuff.find({"attributes.make":"Subaru"}).explain()
{
"cursor" : "BtreeCursor attributes.make_1",
"nscanned" : 2,
"nscannedObjects" : 2,
"n" : 2,
"millis" : 0,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {
    "attributes.make" : [
        [
            "Subaru",
            "Subaru"
        ]
    ]
}
}

vs

db.stuff.find({attributes:{make:"Subaru"}}).explain()
{
"cursor" : "BasicCursor",
"nscanned" : 2,
"nscannedObjects" : 2,
"n" : 0,
"millis" : 1,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {

}
}

Is there a way to get the document style query to hit the index? The reason is that when constructing queries from my persistent objects it's much easier to serialize them out as documents as opposed to something using dot notation.

I'll also add that we're using a home grown data mapper layer built w/ Jackson. Would using something like Morphia help with properly constructing these queries?

like image 608
Adam B Avatar asked Mar 14 '12 15:03

Adam B


1 Answers

Did some more digging and this thread explains what's going with the sub-document query. My problem above was that to make the sub-document based query act like the dot-notation I needed to use elemMatch.

db.stuff.find({"attributes":{"$elemMatch" : {"make":"Subaru"}}}).explain()
{
"cursor" : "BtreeCursor attributes.make_1",
"nscanned" : 2,
"nscannedObjects" : 2,
"n" : 0,
"millis" : 2,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {
    "attributes.make" : [
        [
            "Subaru",
            "Subaru"
        ]
    ]
}
}
like image 102
Adam B Avatar answered Sep 28 '22 05:09

Adam B