Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB indexes and the $or operator

Sorry if this has been asked before. I couldn't find a definitive answer. Can I query on a mongodb index if my query contains the $or operator? My query looks something like this:

    // find everything in the collection
    $cursor = $collection->find(array(
   '$or' => array( 
        array('album_id' => array(
            '$in' => $this->my_album_ids
            ),
        'type' => array(
            '$in' => array('like','comment')
            )
         ),
       array(
    'user_id' => (int)session_item('user_id'),
        'type' => 'message',
        'reply' => 'no'
         )
       ),
        'timestamp' => array('$gt' => (int)$since)))->sort(array('timestamp'=>-1))->skip($start)->limit($amount);  

The Example is in PHP, but I guess this is applicable to any language.

Update:

The following are my indexes, but the above query does not use them. It looks right to me though.

    $collection->ensureIndex(array(
        'album_id' => 1,
        'type' => 1,
        'timestamp' => -1,
    ));

    $collection->ensureIndex(array(
        'user_id' => 1,
        'type' => 1,
        'reply' => 1,
        'timestamp' => -1,
    ));

Here is my explain()

Array
(
    [cursor] => BasicCursor
    [nscanned] => 12
    [nscannedObjects] => 12
    [n] => 6
    [scanAndOrder] => 1
    [millis] => 0
    [nYields] => 0
    [nChunkSkips] => 0
    [isMultiKey] => 
    [indexOnly] => 
    [indexBounds] => Array
        (
        )

    [allPlans] => Array
        (
            [0] => Array
                (
                    [cursor] => BasicCursor
                    [indexBounds] => Array
                        (
                        )

                )

        )

    [oldPlan] => Array
        (
            [cursor] => BasicCursor
            [indexBounds] => Array
                (
                )

        )

)
like image 309
nlyn Avatar asked Jul 29 '11 11:07

nlyn


People also ask

What is $or in MongoDB?

MongoDB provides different types of logical query operators and $or operator is one of them. This operator is used to perform logical OR operation on the array of two or more expressions and select or retrieve only those documents that match at least one of the given expression in the array.

Does MongoDB $in use index?

Generally, MongoDB only uses one index to fulfill most queries. However, each clause of an $or query may use a different index, and in addition, MongoDB can use an intersection of multiple indexes.

What are indexes in MongoDB?

Indexes are special data structures [1] that store a small portion of the collection's data set in an easy to traverse form. The index stores the value of a specific field or set of fields, ordered by the value of the field.

How does MongoDB decide which index to use?

MongoDB uses multikey indexes to index the content stored in arrays. If you index a field that holds an array value, MongoDB creates separate index entries for every element of the array. These multikey indexes allow queries to select documents that contain arrays by matching on element or elements of the arrays.


2 Answers

Yes, an $or query will use indexes as appropriate. For example :

> db.test.ensureIndex({a:1})
> db.test.ensureIndex({b:1})
> db.test.find({$or:[{a:1}, {b:2}]}).explain()
{
        "clauses" : [
                {
                        "cursor" : "BtreeCursor a_1",
                        "nscanned" : 0,
                        "nscannedObjects" : 0,
                        "n" : 0,
                        "millis" : 0,
                        "nYields" : 0,
                        "nChunkSkips" : 0,
                        "isMultiKey" : false,
                        "indexOnly" : false,
                        "indexBounds" : {
                                "a" : [
                                        [
                                                1,
                                                1
                                        ]
                                ]
                        }
                },
                {
                        "cursor" : "BtreeCursor b_1",
                        "nscanned" : 0,
                        "nscannedObjects" : 0,
                        "n" : 0,
                        "millis" : 1,
                        "nYields" : 0,
                        "nChunkSkips" : 0,
                        "isMultiKey" : false,
                        "indexOnly" : false,
                        "indexBounds" : {
                                "b" : [
                                        [
                                                2,
                                                2
                                        ]
                                ]
                        }
                }
        ],
        "nscanned" : 0,
        "nscannedObjects" : 0,
        "n" : 0,
        "millis" : 1
}
like image 56
Remon van Vliet Avatar answered Oct 22 '22 19:10

Remon van Vliet


Mongo use no IndexBounds on an sorted OR Query. Try

db.test.find({$or:[{a:1}, {b:2}]}).sort(somesort).explain();

and IndexBounds use with $minElement and $maxElement

like image 27
r4u Avatar answered Oct 22 '22 19:10

r4u