Mittenchops
Mittenchops

Reputation: 19654

pymongo or mongo solution to list all keys in a collection

I've seen this answer, and am familiar with variety.js

...but I'm wondering if there's any inbuilt mongo command to easily list all the keys in a mongo db collection---the same way I can show dbs, and show collections, it would be great if once within a collection I could "show keys." I use variety.js for overall statistics, but it's a little slow, and sometimes I just want the list of keys.

If this functionality does not exist, what's the easiest, fastest, or most compact way to get this list? (It'd be great to get all 3 solutions with some comparison!)

Upvotes: 1

Views: 2276

Answers (4)

SuperJudeFruit
SuperJudeFruit

Reputation: 11

Try to achieve the same goal. I use Python 3.x and Pymongo.

My solution work for nested dict and nested list (amazing uh ?)

This function return a list of string that contains all path.

Let's take this nested mongo document :

{
    "_id" : ObjectId("5d5166ab7773870c1e57c638"),
    "eventId" : NumberLong(1),
    "estimatedCharacterization" : {
        "snrVerticalAxis" : 5.0,
        "snrHorizontalAxis" : 5.0,
        "distance" : 0.0,
        "magnitude" : 0.0
    },
    "definition" : {
        "requestType" : "DUST_DEVIL",
        "requestedChannels" : [ 
            {
                "startTime" : {
                    "utc" : ISODate("2003-06-25T22:35:37.000Z"),
                    "utcString" : "2003-176T22:35:37.000",
                    "lmst" : "-5482T10:06:09.956",
                    "sclk" : NumberLong(109852537000),
                    "lobt" : NumberLong(112493764823),
                    "aobt" : NumberLong(109857192936)
                },
                "endTime" : {
                    "utc" : ISODate("2003-06-26T05:27:27.000Z"),
                    "utcString" : "2003-177T05:27:27.000",
                    "lmst" : "-5482T16:46:58.822",
                    "sclk" : NumberLong(109877247000),
                    "lobt" : NumberLong(112519067586),
                    "aobt" : NumberLong(109881902665)
                },
                "minDwnSamplRate" : 0.05
            }
        ]
    },
}

with my code will return :

eventId
estimatedCharacterization.snrVerticalAxis
estimatedCharacterization.snrHorizontalAxis
estimatedCharacterization.distance
estimatedCharacterization.magnitude
definition.requestType
definition.requestedChannels.XX.minDwnSamplRate
definition.requestedChannels.XX.startTime.utc
definition.requestedChannels.XX.startTime.utcString
definition.requestedChannels.XX.startTime.lmst
definition.requestedChannels.XX.startTime.sclk
definition.requestedChannels.XX.startTime.lobt
definition.requestedChannels.XX.startTime.aobt
definition.requestedChannels.XX.endTime.utc
definition.requestedChannels.XX.endTime.utcString
definition.requestedChannels.XX.endTime.lmst
definition.requestedChannels.XX.endTime.sclk
definition.requestedChannels.XX.endTime.lobt
definition.requestedChannels.XX.endTime.aobt

Here is the code (based on code of other comment, because he was very clear) :

def find_all_keys(collection):
    def find_keys_in_doc(doc, pre=""):
        found_keys = []
        append = found_keys.append
        if isinstance(doc, dict):
            for k,v in doc.items():
                if isinstance(v, dict):
                    found_keys += find_keys_in_doc(v, pre=pre+k+".")
                elif isinstance(v, list):
                    found_keys += find_keys_in_doc(v, pre=pre+k+".")
                else:
                    append(pre + k)
        elif isinstance(doc, list):
            for v in doc:
                if isinstance(v, dict):
                    found_keys += find_keys_in_doc(v, pre=pre+"XX"+".")
                elif isinstance(v, list):
                    found_keys += find_keys_in_doc(v, pre=pre+"XX"+".")
                else:
                    append(pre + str(v))

        return found_keys
    all_keys = []
    for doc in collection:
        all_keys += find_keys_in_doc(doc)
    return sorted(set(all_keys))

Have fun :)

Upvotes: 0

Mike K.
Mike K.

Reputation: 21

Had/have a similar question. Came up with this less than elegant solution in the mean time, using Python 3.4 and Pymongo (thus assumes the argument "collection" is an iterator full of dicts).

This is minimally tested:

def find_all_keys(collection):
    def find_keys_in_doc(doc, pre=""):
        found_keys = []
        append = found_keys.append

        for k,v in doc.items():
            if type(v) is dict:
                found_keys += find_keys_in_doc(v, pre=pre+k+".")
            else:
                append(k)

        return found_keys

    all_keys = []

    for doc in collection:
        all_keys += find_keys_in_doc(doc)

    return sorted(set(all_keys))

Upvotes: 2

zarehb
zarehb

Reputation: 21

I do

db.users.find({}).limit(1).map(docs  => Object.keys(docs))

Upvotes: 0

Mittenchops
Mittenchops

Reputation: 19654

As of July 22, 2013, there is no mongodb-native way of accomplishing this. You'll need to use variety.js.

Upvotes: 0

Related Questions