vkstack
vkstack

Reputation: 1644

How to pick a multiple element from an embedded array in a MONGO document

I have a collection of documents and each document is of the following format:

{
    "file_id" : 2,
    "data" : [ 
        {
            "category" : "Auto1",
            "code_id" : 1
        }, 
        {
            "category" : "Auto2",
            "code_id" : 2
        }, 
        {
            "category" : "Auto3",
            "code_id" : 3
        }, 
        {
            "category" : "Workers1",
            "code_id" : 4
        }, 
        {
            "category" : "Workers2",
            "code_id" : 5
        }, 
        {
            "category" : "Workers3",
            "code_id" : 6
        }
   ]
}

Other similar documents are there and I want to query with file_id and code_id in data array.

The query should be like file_id = 2, data.code_id = [2,4,5,8]. Result should contain the document with embedded documents (multiple embedded documents) which have code_id from the array specified above.

I tried

db.collectionName.findOne({
    "file_id": 1, 
    "data.code_id": { "$in": [2,4,5,8] }
}, { "file": 1, "data.$": 1 })

This returns single embedded document as written in official documentation but I want multiple embedded documents, what should I do?

Required output

{
    "file_id" : 2,
    "data" : [
        {
            "category" : "Auto2",
            "code_id" : 2
        },
        {
            "category" : "Workers1",
            "code_id" : 4
        },
        {
            "category" : "Workers2",
            "code_id" : 5
        }
   ]
}

Upvotes: 1

Views: 642

Answers (1)

chridam
chridam

Reputation: 103325

Best use the $filter operator which allows you to select a subset of the array to return based on the specified condition. As for the condition, use the $setIsSubset operator which takes two arrays and returns true when the first array is a subset of the second, including when the first array equals the second array, and false otherwise.

var codeIds = [2,4,5,8];
db.collectionName.aggregate([
    { "$match": { "data.code_id": { "$in": codeIds }, "file_id": 2 } },
    { 
        "$project": {
            "file_id": 1,
            "data": {
                "$filter": {
                    "input": '$data',
                    "as": 'item',
                    "cond": { "$setIsSubset": [ ["$$item.code_id"], codeIds ] }
                }
            }
        }
    }
])

Upvotes: 2

Related Questions