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

Aggregation exchange partitioning does not work correctly for dotted keys, results in invariant() failure

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Critical - P2 Critical - P2
    • 4.1.4
    • Affects Version/s: 4.1.2
    • Component/s: Aggregation Framework
    • Labels:
      None
    • Fully Compatible
    • ALL
    • Hide
      (function() {
          "use strict";
      
          db.c.drop();
          assert.commandWorked(db.c.insert({a: {b: -1}}));
          assert.commandWorked(db.c.insert({a: {b: 1}}));
      
          let result = assert.commandWorked(db.runCommand({
              aggregate: "c",
              pipeline: [],
              exchange: {
                  policy: "range",
                  consumers: NumberInt(2),
                  bufferSize: NumberInt(1024),
                  key: {"a.b": 1},
                  boundaries: [{"a.b": MinKey}, {"a.b": 0}, {"a.b": MaxKey}],
                  consumerids: [NumberInt(0), NumberInt(1)]
              },
              cursor: {batchSize: 0}
          }));
          assert.eq(result.cursors.length, 2);
          assert.eq(result.cursors[0].ok, true);
          assert.eq(result.cursors[1].ok, true);
          let firstCursorId = result.cursors[0].cursor.id;
          let secondCursorId = result.cursors[1].cursor.id;
      
          let firstGetMore =
              assert.commandWorked(db.runCommand({getMore: firstCursorId, collection: "c"}));
          printjson(firstGetMore);
      
          let secondGetMore =
              assert.commandWorked(db.runCommand({getMore: secondCursorId, collection: "c"}));
          printjson(secondGetMore);
      }());
      
      Show
      (function() { "use strict" ; db.c.drop(); assert .commandWorked(db.c.insert({a: {b: -1}})); assert .commandWorked(db.c.insert({a: {b: 1}})); let result = assert .commandWorked(db.runCommand({ aggregate: "c" , pipeline: [], exchange: { policy: "range" , consumers: NumberInt(2), bufferSize: NumberInt(1024), key: { "a.b" : 1}, boundaries: [{ "a.b" : MinKey}, { "a.b" : 0}, { "a.b" : MaxKey}], consumerids: [NumberInt(0), NumberInt(1)] }, cursor: {batchSize: 0} })); assert .eq(result.cursors.length, 2); assert .eq(result.cursors[0].ok, true ); assert .eq(result.cursors[1].ok, true ); let firstCursorId = result.cursors[0].cursor.id; let secondCursorId = result.cursors[1].cursor.id; let firstGetMore = assert .commandWorked(db.runCommand({getMore: firstCursorId, collection: "c" })); printjson(firstGetMore); let secondGetMore = assert .commandWorked(db.runCommand({getMore: secondCursorId, collection: "c" })); printjson(secondGetMore); }());
    • Query 2018-09-24, Query 2018-10-08, Query 2018-10-22

      When using range-based partitioning, the Exchange class is responsible for extracting the value of the key on which we are partitioning. In practice, this will be the shard key. This key extraction is not implemented properly when the key pattern contains a dotted field:

      https://github.com/mongodb/mongo/blob/f45a68e589850bbf43c9d656bbbffa0d6b1efc79/src/mongo/db/pipeline/document_source_exchange.cpp#L284

      This can cause an invariant to be tripped when attempting to assign an input document to a particular exchange partition. See the repro steps for a detailed example.

            Assignee:
            Unassigned Unassigned
            Reporter:
            david.storch@mongodb.com David Storch
            Votes:
            0 Vote for this issue
            Watchers:
            8 Start watching this issue

              Created:
              Updated:
              Resolved: