Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-13677

Query planner should traverse through $all while handling $elemMatch object predicates

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major - P3
    • Resolution: Fixed
    • Affects Version/s: 2.6.0, 2.6.1-rc0
    • Fix Version/s: 2.6.1, 2.7.0
    • Component/s: Querying
    • Labels:
      None
    • Operating System:
      ALL
    • Backport Completed:
    • Steps To Reproduce:
      Hide

      > t.drop();
      > t.ensureIndex({'a.b.c.d': 1});
      > t.find({z: 1, "a.b": {$elemMatch: {c: {$all: [{$elemMatch: {d: 0}}]}}}});

      Show
      > t.drop(); > t.ensureIndex({'a.b.c.d': 1}); > t.find({z: 1, "a.b": {$elemMatch: {c: {$all: [{$elemMatch: {d: 0}}]}}}});

      Description

      Issue Status as of April 30, 2014

      ISSUE SUMMARY
      Queries which have the format below fail when there's an index reaching into the deepest subfield. The format is an $elemMatch operator that has an $all descendent, which in turn has another $elemMatch inside:

      db.coll.find({z: 1, "a.b": {$elemMatch: {c: {$all: [{$elemMatch: {d: 0}}]}}}})

      USER IMPACT
      Low user impact due to the very specific format of the query required to trigger the bug.

      WORKAROUNDS
      If the $all operator is rewritten as an $and this issue is not triggered:

      db.coll.find({z: 1, "a.b": {$elemMatch: {$and: [{c: [{$elemMatch: {d: 0}}]}]}}})

      RESOLUTION
      The bug arose from the query planner failing to consider predicates nested inside an $elemMatch-$all-$elemMatch chain. The planner logic was adjusted so that these predicates are no longer ignored.

      AFFECTED VERSIONS
      Version 2.6.0 is affected by this issue.

      PATCHES
      The patch is included in the 2.6.1 production release.

      Original description

      See the code here:

      https://github.com/mongodb/mongo/blob/a7f594977627996aa8731e936ef9c3801d512fc0/src/mongo/db/query/planner_access.cpp#L484-L497

      This function collects predicates from inside an $elemMatch object. Right now it traverses deeply through AND nodes and other ELEM_MATCH_OBJECT nodes. It should also traverse deeply through ALL. Failing to do so means that the access planner might miss predicates which are tagged to use the index, and hence fail to properly build the access plan.

        Attachments

          Activity

            People

            • Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: