summaryrefslogtreecommitdiff
path: root/jstests/core/index_elemmatch2.js
blob: ecd240352848e4b210c98cadf48aa1c712e40f0d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/**
 * Test that queries containing $elemMatch correctly use an index if each child expression is
 * compatible with the index.
 */
(function() {
    "use strict";

    load("jstests/libs/analyze_plan.js");

    const coll = db.elemMatch_index;
    coll.drop();

    assert.writeOK(coll.insert({a: 1}));
    assert.writeOK(coll.insert({a: [{}]}));
    assert.writeOK(coll.insert({a: [1, null]}));
    assert.writeOK(coll.insert({a: [{type: "Point", coordinates: [0, 0]}]}));

    assert.commandWorked(coll.createIndex({a: 1}, {sparse: true}));

    function assertIndexResults(coll, query, useIndex, nReturned) {
        const explainPlan = coll.find(query).explain("executionStats");
        assert.eq(isIxscan(explainPlan.queryPlanner.winningPlan), useIndex);
        assert.eq(explainPlan.executionStats.nReturned, nReturned);
    }

    assertIndexResults(coll, {a: {$elemMatch: {$exists: false}}}, false, 0);

    // An $elemMatch predicate is treated as nested, and the index should be used for $exists:true.
    assertIndexResults(coll, {a: {$elemMatch: {$exists: true}}}, true, 3);

    // $not within $elemMatch should not attempt to use a sparse index for $exists:false.
    assertIndexResults(coll, {a: {$elemMatch: {$not: {$exists: false}}}}, false, 3);
    assertIndexResults(coll, {a: {$elemMatch: {$gt: 0, $not: {$exists: false}}}}, false, 1);

    // $geo within $elemMatch should not attempt to use a non-geo index.
    assertIndexResults(
        coll,
        {
          a: {
              $elemMatch: {
                  $geoWithin: {
                      $geometry:
                          {type: "Polygon", coordinates: [[[0, 0], [0, 1], [1, 0], [0, 0]]]}
                  }
              }
          }
        },
        false,
        1);

    // $in with a null value within $elemMatch should use a sparse index.
    assertIndexResults(coll, {a: {$elemMatch: {$in: [null]}}}, true, 1);

    // $eq with a null value within $elemMatch should use a sparse index.
    assertIndexResults(coll, {a: {$elemMatch: {$eq: null}}}, true, 1);

    // A negated regex within $elemMatch should not use an index, sparse or not.
    assertIndexResults(coll, {a: {$elemMatch: {$not: {$in: [/^a/]}}}}, false, 3);

    coll.dropIndexes();
    assert.commandWorked(coll.createIndex({a: 1}));
    assertIndexResults(coll, {a: {$elemMatch: {$not: {$in: [/^a/]}}}}, false, 3);
})();