Pergunta

I have a search function that looks like this:

mongoDB search function

The criteria from this search is passed through to MongoDB's find() method as a criteria object, e.g:

{
     designer: "Designer1".
     store: "Store1",
     category: "Category1",
     name: "Keyword",
     gender: "Mens",
     price: {$gte: 50}
}

I'm only just learning about indexes in MongoDB so please bear with me. I know I can create an index on each individual field, and I can also create a multi-index on several fields. For instance, for one index I could do:

db.products.ensureIndex({designer: 1, store: 1, category: 1, name: 1, gender: 1, price: 1}) 

The obvious issue arises if someone searches for, say, a category, but not a designer or store it won't be indexed.

I'm currently looking up these terms using an $and operator, so my question is:

How can I create an index that allows for this type of searching with flexibility? Do I have to create an index for each possible combination of these 6 terms? Or if I use $and in my search will it be enough to index each individual term and I'll get the best performance?

Foi útil?

Solução

$and won't work as MongoDB can only use one index per query at the moment. So if you create an index on each field that you search on, MongoDB will select the best fitting index for that query pattern. You can try with explain() to see which one is selected.

Creating an index for each possible combination is probably not a good idea, as you'd need 6 * 5 * 4 * 3 * 2 * 1 indexes, which is 720 indexes... and you can only have 63 indexes. You could pick the most likely ones perhaps but that won't help a lot.

One solution could be to store your data differently, like:

{
    properties: [
        { key: 'designer', value: "Designer1" },
        { key: 'store', value: "Store1" },
        { key: 'category', value: "Category1" },
        { key: 'name', value: "Keyword" },
        { key: 'gender', value: "Mens" },
        { key: 'price', value: 70 },
    ]
}

Then you can create one index on:

db.so.ensureIndex( { 'properties.key': 1, 'properties.value': 1 } );

And do searches like:

db.so.find( { $and: [ 
    { properties: { $elemMatch: { key: 'designer', value: 'Designer1' } } }, 
    { properties: { $elemMatch: { key: 'price', value: { $gte: 30 } } } } 
] } )

db.so.find( { $and: [ 
    { properties: { $elemMatch: { key: 'price', value: { $gte: 45 } } } } 
] } )

In both cases, the index is used, but only for the first part of the $and element right now. So do check which key type has the most values, and order your $and elements accordingly in the query.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top