Kalaeman
Kalaeman

Reputation: 27

MongoDB query - get the values of all occurences of a specific field in a nested document with undefined tree like structure

I have mongoDB documents with a recursive, tree-like, undefined structure. Only thing I know is that there are fields "ref" that contain a string. I would like to get the values of all occurrences of this "ref" in my tree nested documents. For example :

   "properties":{
      "title":{
         "ref":"bannerTitle"
      },
      "buttons":{
         "items":{
            "ref":"button"
         }
      }
   }

I would like to have :

["bannerTitle", "button"]

These "ref" fields can be anywhere in my documents and the documents have no depth limit.

I'm new to MongoDB but I did not find anything from the documentation or my research that would do the job using aggregations. Is there a way to do it ? I would like to create a view of this if possible.

Upvotes: 2

Views: 307

Answers (1)

Valijon
Valijon

Reputation: 13103

It is not possible with MongoDB aggregation because it has very limited syntax.

You may execute js code and store the result inside a collection:

Input

{
    "_id" : ObjectId("5e2f795cc23d78cc72e38f30"),
    "properties" : {
        "title" : {
            "ref" : "bannerTitle"
        },
        "buttons" : {
            "items" : {
                "ref" : "button"
            }
        }
    }
}

{
    "_id" : ObjectId("5e2f7b2ac23d78cc72e38f77"),
    "properties" : {
        "foo" : {
            "bar" : {
                "buz" : {
                    "ref" : "foobarbuz"
                }
            }
        },
        "title" : {
            "ref" : "bannerTitle"
        },
        "buttons" : {
            "items" : {
                "ref" : "button"
            }
        }
    }
}

db.getCollection('collection').find({}).forEach(function(doc){
    function _(obj, result){
        //Iterate
        for(var key in obj){
            //If key is ref, we insert inside result new value
            if(key == "ref"){
                result.push(obj[key]);
            // If value is object, we call recursive function
            } else if (typeof(obj[key]) == "object"){
                result = _(obj[key], result)
            }
        }
        return result;
    }

    print(_(doc, []));
})

Output

[
    "bannerTitle",
    "button"
]

[
    "foobarbuz",
    "bannerTitle",
    "button"
]

Upvotes: 0

Related Questions