how tomongodb

Get the Names of All Keys in a MongoDB Collection

By January 18, 2019 August 19th, 2019 No Comments

In order to validate your schema, debug for typos in fields, or find fields that aren’t supposed to be set, you’ll need to get an understanding of all the keys in your MongoDB collection.

Many MongoDB-as-a-service companies offer an easy way to do this right in the UI, including ObjectRocket. Seasoned MongoDB users typically start with an object-document mapper (ODM), such as Mongoose for JS or Mongoengine for Python, so they can build a consistent schema for their application and reduce typos. (ODMs also do type validation, so you aren’t accidentally putting a string in a field that has integers and has math applied to it.)

If you don’t have a service or ODM, there are several other methods you can use to access the keys. Here are the best ways we’ve found to get all the keys in a MongoDB collection for different circumstances.

An example

db.activities.insert( { type : [‘indoor’, 'outdoor' , ‘mixed’] } );
db.activities.insert( { activity : 'cycling' } );
db.activities.insert( { activity : ‘skiing’, location: ‘Alpes’, } );
db.activities.insert( { equipment : [‘paddles’,‘sunglasses’] } );

You’d like to get the unique keys:
type, activity, equipment, location

MapReduce

You can do this with MapReduce:

mr = db.runCommand({ "mapreduce" : "activities", "map" : function() { for (var key in this) { emit(key, null); } }, "reduce" : function(key, stuff) { return null; }, "out": "activities" + "_keys" })

Once that’s complete, run the distinct command on the resulting collection to find all keys:

db.activities_keys.distinct("_id")

If you want to get a list of all the unique keys in a subdocument, just modify this line:

for (var key in this.first_level.second_level.nth_level) { emit(key, null); }

Aggregation

You can also use aggregation. This method works with all drivers that support the aggregate framework. With your aggregations, $sample or $limit can be used to reduce overhead.

Note: Running with primary read preference may impact performance. Consider running with secondary read preference.

Use aggregation with $objectToArrray (available in version 3.4.4 and up) to convert all top key and value pairs into document arrays followed by $unwind and $group with $addToSet to get distinct keys across entire collection.

$$ROOT for referencing the top level document.

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

Get keys in a single document

You can also use aggregation to get keys in a single document:

db.activities.aggregate([ {"$project":{"arrayofkeyvalue":{"$objectToArray":"$$ROOT"}}}, {"$project":{"keys":"$arrayofkeyvalue.k"}} ])

Mongo shell

You can also try this under mongo shell client:

var allKeys = {}; db.YOURCOLLECTION.find().forEach(function(doc){Object.keys(doc).forEach(function(key){allKeys[key]=1})}); allKeys;

Output fields for a single document

If you need the output of fields for a single document in a collection (since the others may all have completely different keys) use the following:

doc=db.thinks.findOne(); for (key in doc) print(key);

Python

Or, you can use Python. This returns the set of all top-level keys in the collection:

#Using pymongo and connection named 'db' reduce( lambda all_keys, rec_keys: all_keys | set(rec_keys), map(lambda d: d.keys(), db.things.find()), set() )

JavaScript

Or, you can use JavaScript:

db.collection('collectionName').mapReduce( function() { for (var key in this) { emit(key, null); } }, function(key, stuff) { return null; }, { "out": "allFieldNames" }, function(err, results) { var fields = db.collection('allFieldNames').distinct('_id'); fields .then(function(data) { var finalData = { "status": "success", "fields": data }; res.send(finalData); delteCollection(db, 'allFieldNames'); }) .catch(function(err) { res.send(err); delteCollection(db, 'allFieldNames'); }); });

After reading the newly created collection “allFieldNames”, delete it.

db.collection("allFieldNames").remove({}, function (err,result) { db.close(); return; });

So many options…

You’ve got a lot of options to get these Mongo keys! If you’re overwhelmed by MongoDB management and want to focus on your code instead of database management, we’re here for you. Give our database platform and our white glove support a try for free.