Get unique set of pairs of ObjectIds using MongoDB aggregation -


so i'm @ stage in aggregation pipeline , documents this:

{     { a: 'objectida', b: 'objectidb' },     { a: 'objectidb', b: 'objectida' },     { a: 'objectidc', b: 'objectidb' },     { a: 'objectida', b: 'objectidc' },     ... } 

how filter these documents unique pairs of objectids?

if "unique pair" mean "objecta" , "objectb" in order need like:

db.collection.aggregate([     { "$project": {        "combined": {            "$map": {                "input": { "$literal": ["a","b"] },                "as": "i",                "in": { "$cond": [                    { "$eq": [ "$$i", "a" ] },                    "$a",                    "$b"                ]}            }        }     }},     { "$unwind": "$combined" },     { "$sort": { "_id": 1, "combined": 1 } },     { "$group": {         "_id": "$_id",         "combined": { "$push": "$combined" }     }},     { "$group": {         "_id": "$combined"     }} ]) 

which produces:

{ "_id" : [ "objectida", "objectidb" ] } { "_id" : [ "objectidb", "objectidc" ] } { "_id" : [ "objectida", "objectidc" ] } 

so key points there are:

  1. get elements array
  2. sort arrary in consistent order
  3. group on consistently ordered arrays

that uses operators introduced mongodb 2.6, can same earlier versions:

db.collection.aggregate([     { "$project": {         "a": 1,         "b": 1,         "type": { "$const": [ "a", "b" ] }     }},     { "$unwind": "$type" },     { "$group": {         "_id": "$_id",         "combined": {             "$push": {                 "$cond": [                     { "$eq": [ "$type", "a" ] },                     "$a",                     "$b"                 ]             }         }     }},     { "$unwind": "$combined" },     { "$sort": { "_id": 1, "combined": 1 } },     { "$group": {         "_id": "$_id",         "combined": { "$push": "$combined" }     }},     { "$group": {         "_id": "$combined"     }} ]) 

open shell , insert information "you" presented it:

db.collection.drop(); db.collection.insert([     { a: 'objectida', b: 'objectidb' },     { a: 'objectidb', b: 'objectida' },     { a: 'objectidc', b: 'objectidb' },     { a: 'objectida', b: 'objectidc' } ]); 

now run aggregation statement "exactly" present it, , see same results posted before:

{ "_id" : [ "objectida", "objectidb" ] } { "_id" : [ "objectidb", "objectidc" ] } { "_id" : [ "objectida", "objectidc" ] } 

which removes duplicate occurance of "objectida" , "objectidb" in reverse order.

the consistent ordering about.


Comments