Select the subdocuments where the value of the field is in a certain table

advertisements

I want to filter according the sub documents, but actually I am repeating the document for each sub document. I want one document and a list of sub documents if that is the case.

My data looks like:

{
    "_id" : ObjectId("582eeb5f75f58055246bd22d"),
    "filename" : "file1",
    "cod" : NumberLong(90),
    "subdocs" : [
        {
            "length" : NumberLong(10),
            "desc" : "000"
        },
        {
            "length" : NumberLong(15),
            "desc" : "011"
        },
        {
            "length" : NumberLong(30),
            "desc" : "038"
        }
    ]
}
{
    "_id" : ObjectId("582eeb5f75f58055246bd22e"),
    "filename" : "file2",
    "cod" : NumberLong(95),
    "subdocs" : [
        {
            "length" : NumberLong(11),
            "desc" : "000"
        },
        {
            "length" : NumberLong(21),
            "desc" : "018"
        },
        {
            "length" : NumberLong(41),
            "desc" : "008"
        }
    ]
}

I am using this query to filter for the desc (000, 011) on the subdocs

db.ftmp.aggregate(
    { $match:
        { "subdocs.desc":
            { $in: ["000", "011"] }
        }
    },
    { $unwind : "$subdocs" },
    { $match :
        { "subdocs.desc" :
            { $in:["000", "011"] }
        }
    }
)

But the result shows 3 documents, 1 document for each sub-document that matches with that query.

{
    "_id" : ObjectId("582eeb5f75f58055246bd22d"),
    "filename" : "file1",
    "cod" : NumberLong(90),
    "subdocs" : {
        "length" : NumberLong(10),
        "desc" : "000"
    }
}
{
    "_id" : ObjectId("582eeb5f75f58055246bd22d"),
    "filename" : "file1",
    "cod" : NumberLong(90),
    "subdocs" : {
        "length" : NumberLong(15),
        "desc" : "011"
    }
}
{
    "_id" : ObjectId("582eeb5f75f58055246bd22e"),
    "filename" : "file2",
    "cod" : NumberLong(95),
    "subdocs" : {
        "length" : NumberLong(11),
        "desc" : "000"
    }
}

However I want to get: file1 with the subdocuments with desc 000 and 011, and file2 with the subdocumnt 000

{
    "_id" : ObjectId("582eeb5f75f58055246bd22d"),
    "filename" : "file1",
    "cod" : NumberLong(90),
    "subdocs" : [
        {
            "length" : NumberLong(10),
            "desc" : "000"
        },
        {
            "length" : NumberLong(15),
            "desc" : "011"
        }
    ]
}
{
    "_id" : ObjectId("582eeb5f75f58055246bd22e"),
    "filename" : "file2",
    "cod" : NumberLong(95),
    "subdocs" : {
        "length" : NumberLong(11),
        "desc" : "000"
    }
}

What is the correct way to do that? Any idea?


You just need to add $group & $push. First you $unwind the subdocs to apply the $match followed by $group on id and $push the grouped subdocs.

db.ftmp.aggregate({
    $unwind: "$subdocs"
}, {
    $match: {
        "subdocs.desc": {
            $in: ["000", "011"]
        }
    }
}, {
    $group: {
        _id: "$_id",
        subdocs: {
            $push: "$subdocs"
        },
        filename: {
            $first: "$filename"
        },
        cod: {
            $first: "$cod"
        }
    }
})