Vinod Puliyadi
Vinod Puliyadi

Reputation: 235

Mongodb document traversing

I have a query in mongo db, tried lots of solution but still not found it working. Any help will be appreciated.

How to find all keys named "channel" in document?

db.clients.find({"_id": 69})

{
    "_id" : 69,
    "configs" : {
        "GOOGLE" : {
            "drid" : "1246ABCD",
            "adproviders" : {
                "adult" : [ 
                    {
                        "type" : "landing",
                        "adprovider" : "abc123",
                        "channel" : "abc456"
                    }, 
                    {
                        "type" : "search",
                        "adprovider" : "xyz123",
                        "channel" : "xyz456"
                    }
                ],
                "nonadult" : [ 
                    {
                        "type" : "landing",
                        "adprovider" : "pqr123",
                        "channel" : "pqr456"
                    }, 
                    {
                        "type" : "search",
                        "adprovider" : "lmn123",
                        "channel" : "lmn456"
                    }
                ]
            }
        },
        "channel" : "ABC786",
        "_cls" : "ClientGoogleDoc"
    }
}

Trying to find keys with name channel

db.clients.find({"_id": 69, "channel": true})

Expecting:

{"channels": ["abc456", "xyz456", "ABC786", "xyz456", "pqr456", "lmn456", ...]}

Upvotes: 0

Views: 187

Answers (2)

Craig Blaszczyk
Craig Blaszczyk

Reputation: 972

You can use the $project mongodb operator to get only the value for the specific key. Check the documentation at http://docs.mongodb.org/manual/reference/operator/aggregation/project/

Upvotes: 0

Gillespie
Gillespie

Reputation: 6561

As far as I know, you'd have to use python to recursively traverse the dictionary yourself in order to build the list that you want above:

channels = []

def traverse(my_dict):
    for key, value in my_dict.items():
        if isinstance(value, dict):
            traverse(value)
        else:
            if key == "channel":
                channels.append(value)

traverse({"a":{"channel":"abc123"}, "channel":"xyzzz"})  
print(channels)

output:

['abc123', 'xyzzz']

However, using a thing called projections you can get sort of close to what you want (but not really, since you have to specify all of the channels manually):

db.clients.find({"_id": 69}, {"configs.channel":1})

returns:

{ "_id" : ObjectId("69"), "configs" : { "channel" : "ABC786" } }

If you want to get really fancy, you could write a generator function to generate all the keys in a given dictionary, no matter how deep:

my_dict = { "a": {
                "channel":"abc123",
                "key2": "jjj",
                "subdict": {"deep_key": 5, "channel": "nested"}
            }, 
            "channel":"xyzzz"}

def getAllKeys(my_dict):
    for key, value in my_dict.items():
        yield key, value
        if isinstance(value, dict):
            for key, value in getAllKeys(value):
                yield key, value

for key, value in getAllKeys(my_dict):
    if key == "channel":
        print value

output:

nested
abc123
xyzzz

Upvotes: 1

Related Questions