Distinctive element with condition

advertisements

My documents look like this:

{
    "_id": "1",
    "tags": [
        { "code": "01-01", "type": "machine" },
        { "code": "04-06", "type": "gearbox" },
        { "code": "07-01", "type": "machine" }
    ]
},
{
    "_id": "2",
    "tags": [
        { "code": "03-04","type": "gearbox" },
        { "code": "01-01", "type": "machine" },
        { "code": "04-11", "type": "machine" }
    ]
}

I want to get distinct codes only for tags whose type is "machine". so, for the example above, the result should be ["01-01", "07-01", "04-11"]. How do I do this?


Using $unwind and then $group with the tag as the key will give you each tag in a separate document in your result set:

db.collection_name.aggregate([
    {
        $unwind: "$tags"
    },
    {
        $match: {
            "tags.type": "machine"
        }
    },
    {
        $group: {
            _id: "$tags.code"
        }
    },
    {
        $project:{
            _id:false
            code: "$_id"
        }
    }
]);

Or, if you want them put into an array within a single document, you can use $push within a second $group stage:

db.collection_name.aggregate([
    {
        $unwind: "$tags"
    },
    {
        $match: {
            "tags.type": "machine"
        }
    },
    {
        $group: {
            _id: "$tags.code"
        }
    },
    {
        $group:{
            _id: null,
            codes: {$push: "$_id"}
        }
    }
]);

Another user suggested including an initial stage of { $match: { "tags.type": "machine" } }. This is a good idea if your data is likely to contain a significant number of documents that do not include "machine" tags. That way you will eliminate unnecessary processing of those documents. Your pipeline would look like this:

db.collection_name.aggregate([
    {
        $match: {
            "tags.type": "machine"
        }
    },
    {
        $unwind: "$tags"
    },
    {
        $match: {
            "tags.type": "machine"
        }
    },
    {
        $group: {
            _id: "$tags.code"
        }
    },
    {
        $group:{
            _id: null,
            codes: {$push: "$_id"}
        }
    }
]);