$mergeObjects (aggregation)

Definition

  • $mergeObjects

New in version 3.6.

Combines multiple documents into a single document.

  1. { $mergeObjects: <document> }
  • When used in other expressions, including in the$group stage but not as an accumulator:
  1. { $mergeObjects: [ <document1>, <document2>, ... ] }

The <document> can be any valid expression that resolves to a document.

Behavior

  • mergeObjects ignores null operands. If all theoperands to mergeObjects resolves to null,mergeObjects returns an empty document { }.
  • mergeObjects overwrites the field values as it mergesthe documents. If documents to merge include the same field name, thefield, in the resulting document, has the value from the lastdocument merged for the field.
ExampleResults
  1. { $mergeObjects: [ { a: 1 }, null ] }
  1. { a: 1 }
  1. { $mergeObjects: [ null, null ] }
  1. { }
  1. { $mergeObjects: [ { a: 1 }, { a: 2, b: 2 }, { a: 3, c: 3 } ]}
  1. { a: 3, b: 2, c: 3 }
  1. { $mergeObjects: [ { a: 1 }, { a: 2, b: 2 }, { a: 3, b: null, c: 3 } ]}
  1. { a: 3, b: null, c: 3 }

Examples

$mergeObjects

Create a collection orders with the following documents:

  1. db.orders.insert([
  2. { "_id" : 1, "item" : "abc", "price" : 12, "ordered" : 2 },
  3. { "_id" : 2, "item" : "jkl", "price" : 20, "ordered" : 1 }
  4. ])

Create another collection items with the following documents:

  1. db.items.insert([
  2. { "_id" : 1, "item" : "abc", description: "product 1", "instock" : 120 },
  3. { "_id" : 2, "item" : "def", description: "product 2", "instock" : 80 },
  4. { "_id" : 3, "item" : "jkl", description: "product 3", "instock" : 60 }
  5. ])

The following operation first uses the $lookup stage tojoin the two collections by the item fields and then uses$mergeObjects in the $replaceRoot to mergethe joined documents from items and orders:

  1. db.orders.aggregate([
  2. {
  3. $lookup: {
  4. from: "items",
  5. localField: "item", // field in the orders collection
  6. foreignField: "item", // field in the items collection
  7. as: "fromItems"
  8. }
  9. },
  10. {
  11. $replaceRoot: { newRoot: { $mergeObjects: [ { $arrayElemAt: [ "$fromItems", 0 ] }, "$$ROOT" ] } }
  12. },
  13. { $project: { fromItems: 0 } }
  14. ])

The operation returns the following documents:

  1. { "_id" : 1, "item" : "abc", "description" : "product 1", "instock" : 120, "price" : 12, "ordered" : 2 }
  2. { "_id" : 2, "item" : "jkl", "description" : "product 3", "instock" : 60, "price" : 20, "ordered" : 1 }

$mergeObjects as an Accumulator

Create a collection sales with the following documents:

  1. db.sales.insert( [
  2. { _id: 1, year: 2017, item: "A", quantity: { "2017Q1": 500, "2017Q2": 500 } },
  3. { _id: 2, year: 2016, item: "A", quantity: { "2016Q1": 400, "2016Q2": 300, "2016Q3": 0, "2016Q4": 0 } } ,
  4. { _id: 3, year: 2017, item: "B", quantity: { "2017Q1": 300 } },
  5. { _id: 4, year: 2016, item: "B", quantity: { "2016Q3": 100, "2016Q4": 250 } }
  6. ] )

The following operation uses $mergeObjects as aaccumulator in a $group stage that groups documents by theitem field:

Note

When used as an accumulator, $mergeObjects operatoraccepts a single operand.

  1. db.sales.aggregate( [
  2. { $group: { _id: "$item", mergedSales: { $mergeObjects: "$quantity" } } }
  3. ])

The operation returns the following documents:

  1. { "_id" : "B", "mergedSales" : { "2017Q1" : 300, "2016Q3" : 100, "2016Q4" : 250 } }
  2. { "_id" : "A", "mergedSales" : { "2017Q1" : 500, "2017Q2" : 500, "2016Q1" : 400, "2016Q2" : 300, "2016Q3" : 0, "2016Q4" : 0 } }

Note

If the documents to merge include the same field name, the field inthe resulting document has the value from the last document mergedfor the field.