Question

I have a mongodb data base like this:

{
    "_id" : ObjectId("530d24150fef5d9b065909ca"),
    "name" : "name 1",
    "my_array" : [
        {"key" : "date", "value": 19},
        {"key" : "id", "value": 5}
     ]
}
{
    "_id" : ObjectId("530d24150fef5d9b065909ca"),
    "name" : "name 2",
    "my_array" : [
        {"key" : "date", "value": 9},
        {"key" : "id", "value": 11}
     ]
}
{
    "_id" : ObjectId("530d24150fef5d9b065909ca"),
    "name" : "name 3",
    "my_array" : [
        {"key" : "date", "value": 10},
        {"key" : "id", "value": 13},
        {"key" : "name", "value": 'test'},
     ]
}

I want to make a query which depends on the K-V in my_array. I know to list the items have the key-name:

db.test.find({"my_array.key": 'name'})

But, I don't know how to filter the items with the key-value, Like get the item which key is 'id' and value bigger than 10. I this sample the result must be:

{
    "_id" : ObjectId("530d24150fef5d9b065909ca"),
    "name" : "name 2",
    "my_array" : [
        {"key" : "date", "value": 9},
        {"key" : "id", "value": 11}
     ]
}
{
    "_id" : ObjectId("530d24150fef5d9b065909ca"),
    "name" : "name 3",
    "my_array" : [
        {"key" : "date", "value": 10},
        {"key" : "id", "value": 13},
        {"key" : "name", "value": 'test'},
     ]
}

And, I had tried about the follow command line:

db.test.find({"my_array.key": 'id', "my_array.value": {$gt : 10}})
db.test.find({"my_array":{"key": 'id', "value": {$gt : 10}}})

Those are all not work...

Thanks in advance.

Was it helpful?

Solution 2

You can use $elemMatch to achieve the same.

Try following query.

db.test.find({my_array: {$elemMatch: {key: 'id', value: {$gt: 10}}}})

OTHER TIPS

You need to use $elemMatch to find a document that contains both of the elements that match your conditions:

db.test.find(
    {
        "my_array": { "$elemMatch":{ 
            "key": "id", "value": { "$gt" : 10 }
        }}
    },
    {
        "my_array.$": 1
    }
)

Keep in mind that this is matching the document and not the array elements. The use of projection here will only get the first value.

If you have multiple entries to filter within the array you need to use aggregate:

db.test.aggregate([
    { "$match": {
        "my_array": { "$elemMatch":{ 
            "key": "id", "value": { "$gt" : 10 }
        }}
    }},
    { "$unwind": "$my_array" },
    { "$match": {
        "my_array.key": "id",
        "my_array.value": { "$gt" : 10 }
    }},
    { "$group": {
        "_id": "$_id",
        "name": { "$first": "$name" },
        "my_array": { "$push": "$my_array" }
    }}
])

Refer this to find ans of your question.
db.test.find({my_array: {$elemMatch: {key: 'id', value: {$gt: 10}}}})

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top