Mongodb – compound array index mongodb

mongodbnosql

I just realised you can't have a compound index with more than one array with mongodb.
I'm doing a tags,categories and actors search and I have simply stored them as arrays in the document example :

{
url = whatever.com
tags = [tag1,tag2]
actors = [actor1]
categories = [categorie1,categorie2]
}

How should I store them to make the search as fast as possible ? A search of this form:

tag1 AND tag 2 … AND tagN AND categorie1 AND categorie2 … AND categorieN AND actor1 AND actor2 … AND actorn

Where the documents returned would be the videos that all have AT LEAST(so all) those criterias.

Best Answer

You're correct that MongoDB can index only one array per document. This is called Multikey index. The limitation is due to the fact that MongoDB will create one index entry per array element.

So for example if you have an array with 10 elements, MongoDB will create 10 index entries for that single document. If you index more than one array, you can imagine that the number of index entries will go up exponentially, making the overall index impractically large.

One solution to your question is to refactor your document to use only one array, with the key tag, actors, and categories acting as a sub-document key. For example:

> db.test.find()
{
  "_id": ObjectId("597820ef2dbe1d773beb11d4"),
  "url": "whatever.com",
  "values": [
    {"tag": "tag1"},
    {"tag": "tag2"},
    {"actor": "actor1"},
    {"actor": "actor2"},
    {"category": "category1"},
    {"category": "category2"}
  ]
}

You can index this document easily since it only contains one array.

To search for the condition you proposed: tag1 AND tag 2 ... AND tagN AND categorie1 AND categorie2 ... AND categorieN AND actor1 AND actor2 ... AND actorn, you can use the $all operator. For example:

> db.test.find({
    values: {$all: [
        {tag: 'tag1'},
        {tag: 'tag2'},
        {actor: 'actor1'},
        {actor: 'actor2'},
        {category: 'category1'},
        {category: 'category2'}
    ]}
})

Which will return the document shown above.

Please see Query an Array for more methods in querying an array in MongoDB.

Also please see Explain results for methods to observe and optimize your query performance.