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

Aggregate with $merge fails with command error, not write error

    • Type: Icon: Question Question
    • Resolution: Works as Designed
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: None
    • Component/s: None
    • Query 2019-12-16

      An aggregate with $merge will fail with a command error where other operations would typically fail with ok: 1 plus a write error (e.g. duplicate key). Is this the intended behavior? In the design doc for this stage, a duplicate key error is shown to be returned as a command error, but the doc doesn't state any rationale for it being in that format.

      This leads to a weird situation where the aggregate failed with ok: 0, but documents were actually inserted into the into collection with no indication that they were. 

      e.g.

      MongoDB Enterprise repl0:PRIMARY> db.test.find()
      { "_id" : 1 }
      { "_id" : ObjectId("5ddc238fb9cf2f059ec3ba5a") }
      MongoDB Enterprise repl0:PRIMARY> db.other.find()
      { "_id" : 1, "x" : 1 }
      MongoDB Enterprise repl0:PRIMARY> db.runCommand({aggregate: "test", pipeline: [{"$merge": {into: "other", whenMatched: "fail"}}], cursor: {}})
      {
      	"ok" : 0,
      	"errmsg" : "E11000 duplicate key error collection: test.other index: _id_ dup key: { _id: 1.0 }",
      	"code" : 11000,
      	"codeName" : "DuplicateKey",
      	"keyPattern" : {
      		"_id" : 1
      	},
      	"keyValue" : {
      		"_id" : 1
      	}
      }
      MongoDB Enterprise repl0:PRIMARY> db.other.find()
      { "_id" : 1, "x" : 1 }
      { "_id" : ObjectId("5ddc238fb9cf2f059ec3ba5a") }
      

       

      It also presents a problem for statically typed drivers. If the server returns a command error and a write concern error in the same response, those drivers will simply ignore the write concern error, since write concern errors are only generally expected and parsed in the context of write errors (which occur if ok: 1). 

      MongoDB Enterprise repl0:PRIMARY> db.runCommand({aggregate: "test", pipeline: [{"$merge": {into: "other", whenMatched: "fail"}}], cursor: {}, writeConcern: {w: 2, wtimeout: 10}})
      {
      	"writeConcernError" : {
      		"code" : 64,
      		"codeName" : "WriteConcernFailed",
      		"errmsg" : "waiting for replication timed out",
      		"errInfo" : {
      			"wtimeout" : true
      		}
      	},
      	"ok" : 0,
      	"errmsg" : "E11000 duplicate key error collection: test.other index: _id_ dup key: { _id: 1.0 }",
      	"code" : 11000,
      	"codeName" : "DuplicateKey",
      	"keyPattern" : {
      		"_id" : 1
      	},
      	"keyValue" : {
      		"_id" : 1
      	}
      }
      

      e.g. this would just throw/return a CommandError/Exception driver side, with no mention of a write concern error.

      Additionally, if the server only returns a WriteConcernError, the driver will throw a WriteException, as per the drivers' CRUD specification.

      MongoDB Enterprise repl0:PRIMARY> db.runCommand({aggregate: "test", pipeline: [{"$merge": {into: "other"}}], cursor: {}, writeConcern: {w: 2, wtimeout: 10}})
      {
      	"cursor" : {
      		"firstBatch" : [ ],
      		"id" : NumberLong(0),
      		"ns" : "test.test"
      	},
      	"writeConcernError" : {
      		"code" : 64,
      		"codeName" : "WriteConcernFailed",
      		"errmsg" : "waiting for replication timed out",
      		"errInfo" : {
      			"wtimeout" : true
      		}
      	},
      	"ok" : 1,
      }
      

      e.g. this would throw a WriteException(WriteError: null, WriteConcernError: ...).

            Assignee:
            anton.korshunov@mongodb.com Anton Korshunov
            Reporter:
            patrick.freed@mongodb.com Patrick Freed
            Votes:
            0 Vote for this issue
            Watchers:
            8 Start watching this issue

              Created:
              Updated:
              Resolved: