$addToSet (aggregation)
Definition
Changed in version 5.0.
$addToSet returns an array of all unique values that
results from applying an expression
to each document in a group.
The order of the elements in the returned array is unspecified.
$addToSet is available in these stages:
$setWindowFields(Available starting in MongoDB 5.0)
Syntax
$addToSet syntax:
{ $addToSet: <expression> }
For more information on expressions, see Expression Operators.
Behavior
If the value of the expression is an array, $addToSet appends
the whole array as a single element.
If the value of the expression is a document, MongoDB determines that the document is a duplicate if another document in the array matches the to-be-added document exactly. Specifically, the existing document has the exact same fields and values in the exact same order.
Examples
Use in $group Stage
Consider a sales collection with the following documents:
{ "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "date" : ISODate("2014-01-01T08:00:00Z") } { "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1, "date" : ISODate("2014-02-03T09:00:00Z") } { "_id" : 3, "item" : "xyz", "price" : 5, "quantity" : 5, "date" : ISODate("2014-02-03T09:05:00Z") } { "_id" : 4, "item" : "abc", "price" : 10, "quantity" : 10, "date" : ISODate("2014-02-15T08:00:00Z") } { "_id" : 5, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-02-15T09:12:00Z") }
Grouping the documents by the day and the year of the date field,
the following operation uses the $addToSet accumulator to
compute the list of unique items sold for each group:
db.sales.aggregate( [ { $group: { _id: { day: { $dayOfYear: "$date"}, year: { $year: "$date" } }, itemsSold: { $addToSet: "$item" } } } ] )
The operation returns the following results:
{ "_id" : { "day" : 46, "year" : 2014 }, "itemsSold" : [ "xyz", "abc" ] } { "_id" : { "day" : 34, "year" : 2014 }, "itemsSold" : [ "xyz", "jkl" ] } { "_id" : { "day" : 1, "year" : 2014 }, "itemsSold" : [ "abc" ] }
Use in $setWindowFields Stage
New in version 5.0.
Create a cakeSales collection that contains cake sales in the states
of California (CA) and Washington (WA):
db.cakeSales.insertMany( [ { _id: 0, type: "chocolate", orderDate: new Date("2020-05-18T14:10:30Z"), state: "CA", price: 13, quantity: 120 }, { _id: 1, type: "chocolate", orderDate: new Date("2021-03-20T11:30:05Z"), state: "WA", price: 14, quantity: 140 }, { _id: 2, type: "vanilla", orderDate: new Date("2021-01-11T06:31:15Z"), state: "CA", price: 12, quantity: 145 }, { _id: 3, type: "vanilla", orderDate: new Date("2020-02-08T13:13:23Z"), state: "WA", price: 13, quantity: 104 }, { _id: 4, type: "strawberry", orderDate: new Date("2019-05-18T16:09:01Z"), state: "CA", price: 41, quantity: 162 }, { _id: 5, type: "strawberry", orderDate: new Date("2019-01-08T06:12:03Z"), state: "WA", price: 43, quantity: 134 } ] )
This example uses $addToSet in the $setWindowFields
stage to output the unique cake type sales for each state:
db.cakeSales.aggregate( [ { $setWindowFields: { partitionBy: "$state", sortBy: { orderDate: 1 }, output: { cakeTypesForState: { $addToSet: "$type", window: { documents: [ "unbounded", "current" ] } } } } } ] )
In the example:
partitionBy: "$state"partitions the documents in the collection bystate. There are partitions forCAandWA.sortBy: { orderDate: 1 }sorts the documents in each partition byorderDatein ascending order (1), so the earliestorderDateis first.
outputadds each unique caketypeto thecakeTypesForStatearray field using$addToSetthat is run in a documents window.The window contains documents between an
unboundedlower limit and thecurrentdocument. This means$addToSetreturns an array containing the unique caketypefields for the documents between the beginning of the partition and the current document.
In this example output, the cake type array for CA and WA is
shown in the cakeTypesForState field:
{ "_id" : 4, "type" : "strawberry", "orderDate" : ISODate("2019-05-18T16:09:01Z"), "state" : "CA", "price" : 41, "quantity" : 162, "cakeTypesForState" : [ "strawberry" ] } { "_id" : 0, "type" : "chocolate", "orderDate" : ISODate("2020-05-18T14:10:30Z"), "state" : "CA", "price" : 13, "quantity" : 120, "cakeTypesForState" : [ "strawberry", "chocolate" ] } { "_id" : 2, "type" : "vanilla", "orderDate" : ISODate("2021-01-11T06:31:15Z"), "state" : "CA", "price" : 12, "quantity" : 145, "cakeTypesForState" : [ "strawberry", "vanilla", "chocolate" ] } { "_id" : 5, "type" : "strawberry", "orderDate" : ISODate("2019-01-08T06:12:03Z"), "state" : "WA", "price" : 43, "quantity" : 134, "cakeTypesForState" : [ "strawberry" ] } { "_id" : 3, "type" : "vanilla", "orderDate" : ISODate("2020-02-08T13:13:23Z"), "state" : "WA", "price" : 13, "quantity" : 104, "cakeTypesForState" : [ "vanilla", "strawberry" ] } { "_id" : 1, "type" : "chocolate", "orderDate" : ISODate("2021-03-20T11:30:05Z"), "state" : "WA", "price" : 14, "quantity" : 140, "cakeTypesForState" : [ "vanilla", "chocolate", "strawberry" ] }