We have learnt the basics of multi-key indexes in MongoDB. Lets look at an example to demonstrate the multi-key indexing on arrays.
foo: database name
name: collection name
Insert a document
MongoDB shell version: 2.6.1
connecting to: test
> use foo
switched to db foo
> db.name.insert({a: 1, b: 2, c: 3});
WriteResult({ "nInserted" : 1 })
Here we insert {a: 1, b: 2, c: 3} into “name” collection.
Multi-key Indexes and Arrays: MongoDB
Basic Cursor
> db.name.find({a: 1, b: 2})
{ "_id" : ObjectId("53d8982b79142c385cddc607"), "a" : 1, "b" : 2, "c" : 3 }
> db.name.find({a: 1, b: 2}).explain()
{
"cursor" : "BasicCursor",
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 1,
"nscanned" : 1,
"nscannedObjectsAllPlans" : 1,
"nscannedAllPlans" : 1,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"server" : "Satish-PC:27017",
"filterSet" : false
}
We find() the document using fields “a” and “b” and the query/command returns a basic cursor, as we do not have indexing on them.
Related Read: index creation: MongoDB
Lets create index on a and b
> db.name.ensureIndex({a: 1, b: 1});
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
Previous there was only 1 index i.e., on “_id” Now there are 2 indexes – “_id” and “{a: 1, b: 1}”
Btree Cursor with multi-key as false
> db.name.find({a: 1, b: 2}).explain()
{
"cursor" : "BtreeCursor a_1_b_1",
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 1,
"nscanned" : 1,
"nscannedObjectsAllPlans" : 1,
"nscannedAllPlans" : 1,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"a" : [
[
1,
1
]
],
"b" : [
[
2,
2
]
]
},
"server" : "Satish-PC:27017",
"filterSet" : false
}
After creating the index on “a” and “b”, chain explain() method on the same command, and it shows you that, now it returns a Btree Cursor.
Lets insert another document
> db.name.insert({a: [0, 1, 2], b: 2, c: 3});
WriteResult({ "nInserted" : 1 })
Lets insert an array as value to field “a” and scalar values to “b” and “c”.
Btree Cursor with Multi-key true
> db.name.find({a: 1, b: 2})
{ "_id" : ObjectId("53d8982b79142c385cddc607"),
"a" : 1, "b" : 2, "c" : 3 }
{ "_id" : ObjectId("53d8986f79142c385cddc608"),
"a" : [ 0, 1, 2 ], "b" : 2, "c": 3 }
> db.name.find({a: 1, b: 2}).explain()
{
"cursor" : "BtreeCursor a_1_b_1",
"isMultiKey" : true,
"n" : 2,
"nscannedObjects" : 2,
"nscanned" : 2,
"nscannedObjectsAllPlans" : 2,
"nscannedAllPlans" : 2,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"a" : [
[
1,
1
]
],
"b" : [
[
2,
2
]
]
},
"server" : "Satish-PC:27017",
"filterSet" : false
}
Now append explain() method to our command, it shows us that it returns a Btree Cursor and multi-key as true. MongoDB engine need to match every element of the array present in field “a” with the scalar value of field “b”. Hence it uses Multi-Key indexing.
Multi-Key Condition in MongoDB
> db.name.insert({a: [0, 1, 2], b: [3, 4], c: 3});
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 10088,
"errmsg" : "insertDocument :: caused by :: 10088 cannot
index parallel arrays [b] [a]"
}
})
It’s difficult to match every combination of the array elements present inside both “a” and “b” fields. If both keys/indexes has its value as an array, then it gets complicated. Thus, mongoDB doesn’t allow both keys to be arrays. Either one of them must be a scalar value.