The $addToSet accumulator builds an array of unique values while MongoDB groups documents. It is the aggregation-friendly way to answer “what distinct values appeared in this group?”
01
Unique arrays
Skip duplicates automatically in $group.
02
$group syntax
Accumulator form with field or expression.
03
vs $push
When to keep every value vs distinct only.
04
$unwind pattern
Unique scalars from nested arrays.
05
Real reports
Cities, tags, skills, product IDs per group.
06
Gotchas
Array fields, null, object equality.
Fundamentals
Definition and Usage
$addToSet is a MongoDB accumulator used inside the $group stage. For each group, it evaluates an expression on every input document and adds the result to an output array—but only if that exact value is not already in the array.
💡
Beginner tip
Think of $addToSet as “give me every different value I saw,” while $push is “give me every value I saw, even repeats.” Both return arrays; only $addToSet deduplicates.
Typical reports include unique cities per department, distinct product categories sold per store, or a set of user IDs who performed an action. Pair with $match and $sort before grouping for cleaner results.
Foundation
📝 Syntax
$addToSet appears as a field accumulator in $group:
Austin is listed once even though two Engineering documents reference it. Order follows first encounter in the pipeline (do not rely on sorted output unless you sort afterward).
📈 Practical Patterns
Handle array fields, compare accumulators, and shape the final report.
Example 3 — Unique tags with $unwind
When each document stores tags as an array, unwind before grouping:
mongosh
db.articles.aggregate([
{ $unwind: "$tags" },
{
$group: {
_id: "$author",
uniqueTags: { $addToSet: "$tags" }
}
}
]);
// Without $unwind, { $addToSet: "$tags" } would store
// whole arrays as set members—not individual tag strings.
📤 Pattern:
$unwind → one doc per tag → $addToSet collects unique tag strings
How It Works
$unwind emits one document per array element. Then $addToSet deduplicates scalar tag values across all articles by the same author.
Example 4 — $addToSet vs $push side by side
Same grouping with both accumulators shows the difference clearly:
$size counts array elements after deduplication—handy for “how many different products did this department sell?” dashboards.
Compare
📋 $addToSet vs related accumulators
Accumulator
Output
Duplicates
Best for
$addToSet
Array of unique values
Removed
Distinct cities, IDs, tags
$push
Array of all values
Kept
Event history, ordered lists
$sum
Number
N/A
Totals and counts of numbers
$addToSet + $size
Number (distinct count)
N/A
Cardinality per group
🧠 How $addToSet Works
1
Documents enter $group
MongoDB buckets documents by the _id expression (e.g. department name).
Group
2
Evaluate expression
For each document in the bucket, compute the $addToSet expression (field path or formula).
Eval
3
Check uniqueness
If the value is not already in the group array (BSON-equal), append it; otherwise skip.
Dedupe
=
📊
Unique array per group
Each group document contains one array field with all distinct collected values.
Important
📝 Notes
$addToSet is an accumulator—it belongs inside $group, not in $match.
For array fields, $unwind first unless you intentionally want unique whole-array values.
Result arrays are best treated as sets, not sorted lists—use $sortArray in a later stage if order matters.
null may appear once in the set if the expression evaluates to null—filter early with $match when needed.
Do not confuse with update operator $addToSet on updateOne—same name, different context (document updates vs aggregation).
Next in the series: $avg for numeric averages per group.
Wrap Up
Conclusion
$addToSet is the standard MongoDB accumulator when you need distinct values per group: unique cities, product IDs, tags, or any scalar you can extract from documents. Pair it with $unwind for nested arrays and with $size when you only need a count.
When duplicates must be preserved or order is significant, switch to $push instead. For custom fold logic, see $accumulator.
Use $addToSet for distinct-value reports in $group
$unwind array fields when you need unique elements, not unique arrays
Filter nulls and empty strings in $match before grouping
Combine with $size for cardinality metrics
Document whether your UI treats the result as ordered or unordered
❌ Don’t
Use $addToSet when you need every duplicate event ($push instead)
Assume output arrays are sorted alphabetically
Forget that "10" and 10 are different set members
Mix up aggregation $addToSet with update $addToSet syntax
Skip indexes on _id group keys for large collections without testing performance
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about $addToSet
Use these points whenever you build distinct-value aggregation reports.
5
Core concepts
📊01
Unique array
Deduplicates per group.
Basics
📦02
$group only
Accumulator context.
Syntax
🔄03
vs $push
All values vs distinct.
Compare
✂04
$unwind
For nested arrays.
Pattern
🔢05
$size
Count distinct items.
Metric
❓ Frequently Asked Questions
$addToSet collects values into an array during $group and only adds a value if it is not already present. The result is a set of unique values for each group.
Inside the $group stage as an accumulator: { uniqueField: { $addToSet: "$field" } }. It is not a query filter operator—it runs while grouping documents.
$push appends every value (including duplicates). $addToSet skips values already in the array. Use $addToSet for distinct lists; use $push when you need every occurrence or order preserved.
MongoDB generally keeps first-seen order for unique values in the output array, but treat the result as an unordered set unless your use case explicitly requires order.
$addToSet adds the entire array as one element unless you $unwind the field first. To collect unique tags from nested arrays, $unwind before $group, then $addToSet the scalar.
Yes. It deduplicates by value equality (BSON comparison). Two sub-documents with identical fields count as one entry; slightly different objects remain separate entries.
Did you know?
MongoDB also has an update operator named $addToSet for adding unique values to an array field on a single document. The aggregation accumulator you learned here runs inside $group across many documents. Same name, different pipeline stage. See the official $addToSet aggregation docs.