Frakcool
Frakcool

Reputation: 11143

How to query an array of documents in MongoDB

I have an array of objects like this one:

{
    "actions": [{
        "help": {
            "messages": [{}, {}]
        }
    }, {
        "animals": [{
            "sea": {
                "messages": [{}, {}]
            }
        }, {
            "land": {
                "messages": [{}, {}]
            }
        }]
    }]
}

I'm trying to get the messages array from each element. (Only the matched one)

I've tried something like:

db.getCollection('responses').find({"actions": "help"})

And

db.getCollection('responses').find({"actions.animals": "sea"})

With no luck as I'm still getting an empty array.

If this isn't possible, I'm open for alternatives.

I've been looking for similar questions like this one: Mongo db - Querying nested array and objects but in that question they're looking for a specific element inside the "messages" object (in my case) for example. Same as in this other question: Query for a field in an object in array with Mongo? where they're using $elementMatch and I don't think it fits my needs.

I thought that in the Mongo Tutorial: Query array of documents might help, but again, they have a similar structure like mine but they have a property for the help element for example, something like:

{
    "actions": [{
        "action": "help",
        "messages": [{}, {}]
    }, {
        "action": "animals",
        "classifications": [{
            "classification": "sea",
            "messages": [{}, {}]
        }, {
            "classification": "land",
            "messages": [{}, {}]
        }]
    }]
}

Is this the only way to make it to work? Or can I still maintain my original structure?

Edit

After trying @Graciano's answer I'm getting the following:

db.getCollection('responses').aggregate([{
    $project: { "messages":  "$actions.animals.sea.messages" }
}])

Result:

/* 1 */
{
    "_id" : ObjectId("5ac42e65734d1d5beda1f99b"),
    "messages" : [ 
        [ 
            [ 
                {
                    "type" : 0,
                    "speech" : "There are a lot of sea animals, to name a few: "
                }, 
                {
                    "type" : 0,
                    "speech" : "Whale\nFishes\nSharks"
                }
            ]
        ]
    ]
}

Now the error to solve is that it must be a single array, not an array of arrays of arrays of messages... how to solve this?

Upvotes: 0

Views: 1082

Answers (2)

Graciano
Graciano

Reputation: 518

if all you need are the messages you can use an aggregation and create an Array from the elements you want

db.collection.aggregate([
  {$project: { items:  "$actions."+parameter+".messages" },
  {$unwind: "$messages"},
  {$unwind: "$messages"}
}])

Upvotes: 1

Rahul Raj
Rahul Raj

Reputation: 3439

I just updated your query and now it will look like this:

db.collection.aggregate([
{$project: { "messages":  "$actions.animals.sea.messages" }},
{$unwind: "$messages"},
{$unwind: "$messages"}

])

And the result will be: enter image description here

{
 "_id" : ObjectId("5ac5b80dd39d9355012f6af3"),
 "messages" : [ 
    {
        "type" : 0,
        "speech" : "There are a lot of sea animals, to name a few: "
    }, 
    {
        "type" : 0,
        "speech" : "Whale\nFishes\nSharks"
    }
  ]
}

Now you will get only single array, all you need to do $unwind the arrays respectively.

Upvotes: 1

Related Questions