0

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?

2
  • can you provide a sample data set with mixed data (with empty & non-empty arrays in it). I dont see speech keys in ur sample data set. Commented Apr 5, 2018 at 5:23
  • just added an answer with an edit to your query, check it and let me know if that works. Commented Apr 5, 2018 at 5:33

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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"}
}])

4 Comments

I need the messages but just from the matched action, i.e. if help is sent to the query, then I might only get the help messages array from it. In this case, $concatArrays might not be needed, right?
It worked, however you have some typos in the code, may I correct it in your answer? Or do you want to correct it yourself? And also it creates a second array inside the array
Corrected the typos, let me add an edit to my question so you can see the output I get with it.
wasn't clear how you wanted the output. As commented below by @Rahul Raj, you only need to add the $unwind operation

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.