MAYA
MAYA

Reputation: 1335

Retrieve all values of a collection in mongodb

I'm looking to retrieve all values of my collection in a single set :

Example :

` "_id" : {
        "origin" : "xx",
        "destination" : "yy"
    },
    "paths" : [ 
        [ 
            "tt"
        ]
    ]
}

/* 2 */
{
    "_id" : {
        "origin" : "aa",
        "destination" : "bb"
    },
    "paths" : [ 
        [ 
            "cc"
        ]
    ]

}

/* 3 */
{
    "_id" : {
        "origin" : "xy",
        "destination" : "yx"
    },
    "paths" : [ 
        [ 
            "yy", 
            "tt", 
            "cc"
        ]
    ]

}`

Expected output :

Nodes : {"xx", "yy", "aa", "bb","xy", "yx"}

I tried $setUnion but it doesn't work because I have string

$addToset

is impossible to add both fields : "origin" and "destination"

How to retrieve all values of my collection's fields (id.origin and id.destination) to a set?

Thank you

Upvotes: 0

Views: 81

Answers (2)

Saleem
Saleem

Reputation: 8988

Since this is very special case where you want custom formatting, your best bet will be map-reduce feature of MongoDB. However, this formatting can be achieved with help of aggregation framework too. I'm adding both solutions.

Aggregation framework:

db.collection.aggregate([
  {
    $group:{
      _id:null, 
      origin:{
        $addToSet:"$_id.origin"
      }, 
      destination:{
        $addToSet:"$_id.destination"
      }
  }},
  {
    $project:{
      _id:0, 
      Nodes:{
        $setUnion:["$origin","$destination"]
      }
  }}
])

Output:

{ 
    "Nodes" : [
        "yy", 
        "yx", 
        "xx", 
        "bb", 
        "aa", 
        "xy"
    ]
}

Map Reduce:

db.collection.mapReduce(
    function () {
        emit(1, this._id);
    },
    function (key, values) {
        var o = {};
        o.Nodes = [];

        for (var i = 0; i < values.length; i++) {
            o.Nodes.push(values[i].origin);
            o.Nodes.push(values[i].destination);
        }

        return o;
    },
    {
        out: { inline: 1 }
    });

Output:

{ 
    "results" : [
        {
            "_id" : NumberInt(1), 
            "value" : {
                "Nodes" : [
                    "xx", 
                    "yy", 
                    "aa", 
                    "bb", 
                    "xy", 
                    "yx"
                ]
            }
        }
    ], 
    "timeMillis" : NumberInt(22), 
    "counts" : {
        "input" : NumberInt(3), 
        "emit" : NumberInt(3), 
        "reduce" : NumberInt(1), 
        "output" : NumberInt(1)
    }, 
    "ok" : NumberInt(1)
}

results.values.Nodes contains your desired result.

Upvotes: 2

Lakmal Vithanage
Lakmal Vithanage

Reputation: 2777

In the aggregation pipeline first you can have two sets (Originset and DestinationSet) and after that you can use setUnion to have the union set of the two set.

Upvotes: 1

Related Questions