Get names of all keys in the collection

2018-12-31 03:27发布

I'd like to get the names of all the keys in a MongoDB collection.

For example, from this:

db.things.insert( { type : ['dog', 'cat'] } );
db.things.insert( { egg : ['cat'] } );
db.things.insert( { type : [] } );
db.things.insert( { hello : []  } );

I'd like to get the unique keys:

type, egg, hello

19条回答
零度萤火
2楼-- · 2018-12-31 04:03

Maybe slightly off-topic, but you can recursively pretty-print all keys/fields of an object:

function _printFields(item, level) {
    if ((typeof item) != "object") {
        return
    }
    for (var index in item) {
        print(" ".repeat(level * 4) + index)
        if ((typeof item[index]) == "object") {
            _printFields(item[index], level + 1)
        }
    }
}

function printFields(item) {
    _printFields(item, 0)
}

Useful when all objects in a collection has the same structure.

查看更多
不流泪的眼
3楼-- · 2018-12-31 04:05

With Kristina's answer as inspiration, I created an open source tool called Variety which does exactly this: https://github.com/variety/variety

查看更多
初与友歌
4楼-- · 2018-12-31 04:07

We can achieve this by Using mongo js file. Add below code in your getCollectionName.js file and run js file in the console of Linux as given below :

mongo --host 192.168.1.135 getCollectionName.js

db_set = connect("192.168.1.135:27017/database_set_name"); // for Local testing
// db_set.auth("username_of_db", "password_of_db"); // if required

db_set.getMongo().setSlaveOk();

var collectionArray = db_set.getCollectionNames();

collectionArray.forEach(function(collectionName){

    if ( collectionName == 'system.indexes' || collectionName == 'system.profile' || collectionName == 'system.users' ) {
        return;
    }

    print("\nCollection Name = "+collectionName);
    print("All Fields :\n");

    var arrayOfFieldNames = []; 
    var items = db_set[collectionName].find();
    // var items = db_set[collectionName].find().sort({'_id':-1}).limit(100); // if you want fast & scan only last 100 records of each collection
    while(items.hasNext()) {
        var item = items.next(); 
        for(var index in item) {
            arrayOfFieldNames[index] = index;
        }
    }
    for (var index in arrayOfFieldNames) {
        print(index);
    }

});

quit();

Thanks @ackuser

查看更多
君临天下
5楼-- · 2018-12-31 04:10

If you are using mongodb 3.4.4 and above then you can use below aggregation using $objectToArray and $group aggregation

db.collection.aggregate([
  { "$project": {
    "data": { "$objectToArray": "$$ROOT" }
  }},
  { "$project": { "data": "$data.k" }},
  { "$unwind": "$data" },
  { "$group": {
    "_id": null,
    "keys": { "$addToSet": "$data" }
  }}
])

Here is the working example

查看更多
妖精总统
6楼-- · 2018-12-31 04:11

I have 1 simpler work around...

What you can do is while inserting data/document into your main collection "things" you must insert the attributes in 1 separate collection lets say "things_attributes".

so every time you insert in "things", you do get from "things_attributes" compare values of that document with your new document keys if any new key present append it in that document and again re-insert it.

So things_attributes will have only 1 document of unique keys which you can easily get when ever you require by using findOne()

查看更多
听够珍惜
7楼-- · 2018-12-31 04:14

You can use aggregation with new $objectToArrray in 3.4.4 version to convert all top key & value pair into document arrays followed by $unwind & $group with $addToSet to get distinct keys across entire collection.

$$ROOT for referencing the top level document.

db.things.aggregate([
  {"$project":{"arrayofkeyvalue":{"$objectToArray":"$$ROOT"}}},
  {"$unwind":"$arrayofkeyvalue"},
  {"$group":{"_id":null,"allkeys":{"$addToSet":"$arrayofkeyvalue.k"}}}
])

You can use below query for getting keys in a single document.

db.things.aggregate([
  {"$project":{"arrayofkeyvalue":{"$objectToArray":"$$ROOT"}}},
  {"$project":{"keys":"$arrayofkeyvalue.k"}}
])
查看更多
登录 后发表回答