monkeyUser
monkeyUser

Reputation: 4671

Create unique array from two or more documents

I have a collection like this

 {
    "_id" : ObjectId("53a7fb486201281a1f698fe4"),
    "userId" : ObjectId("53a7fade6201281a1f698fd9"),
    "magic" : [
    {
        "power" : 0,
        "mana" : 10,
        "foo" : null,
        "bar" : 150
    },
    {
        "power" : 2,
        "mana" : 2,
        "foo" : 200,
        "bar" : 1
    },
]
}

{
    "_id" : ObjectId("53a7fb486201281a1f698fe4"),
    "userId" : ObjectId("53a7fade6201281a1f698fd9"),
    "magic" : [
    {
        "power" : 20,
        "mana" : 210,
        "foo" : null,
        "bar" : 2150
    },
    {
        "power" : 23,
        "mana" : 23,
        "foo" : 2004,
        "bar" : 14
    },
]
}

{
    "_id" : ObjectId("53a7fb486201281a1f698fe4"),
    "userId" : ObjectId("anotherID"),
    "magic" : [
    {
        "power" : 20,
        "mana" : 210,
        "foo" : null,
        "bar" : 2150
    },
    {
        "power" : 23,
        "mana" : 23,
        "foo" : 2004,
        "bar" : 14
    },
]
}

I want create a unique array "Magic of userId ObjectId("53a7fade6201281a1f698fd9")

I did try this

db.myColl.aggregate([
{       

    '$group': {
            _id: {
                magic: "$magic",
            },
            "allmagic": {
                $push: "$magic"
            },
        },
}
]);

The result is è array of array of all magic of my collection myColl Then I try to use $match

db.myColl.aggregate([
{       

    '$group': {
            _id: {
                magic: "$magic",
            },

            "allmagic": {
                $push: "$magic"
            },
        },
        $match : { "userId" : ObjectId("53a7fade6201281a1f698fd9") }
}
]);

But I have this error exception: A pipeline stage specification object must contain exactly one field.. Then I want use this in node.js (I use mongoose as well)

Upvotes: 0

Views: 78

Answers (1)

Neil Lunn
Neil Lunn

Reputation: 151112

Working with arrays in the aggregation framework and especially across documents you want to use the $unwind operator:

db.myColl.aggregate([

    // Match documents for user id first
    { "$match": { "userId": ObjectId("53a7fade6201281a1f698fd9") }},

    // Unwind the array
    { "$unwind": "$magic" },

    // Group back to a single user document
    { "$group": {
        "_id": "$userId",
        "magic": { "$addToSet": "$magic" }
    }}
])

The $addToSet operator keeps the elements of the array "unique", if you just want to combine without removing duplicates then use $push instead.

Upvotes: 1

Related Questions