MongoDB获取集合中所有键的名称

我想要获取MongoDB集合中所有键的名称。

例如,从这个:

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

我想获得独特的钥匙:

 type, egg, hello 

你可以用MapReduce做到这一点:

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

然后运行不同的结果集合,以find所有的关键:

 db[mr.result].distinct("_id") ["foo", "bar", "baz", "_id", ...] 

以克里斯蒂娜的答案为灵感,我创build了一个名为Variety的开源工具,它完全实现了这个function: https : //github.com/variety/variety

尝试这个:

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

使用python。 返回集合中所有顶级键的集合:

 #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() ) 

如果你的目标集合不是太大,你可以在mongo shell客户端下试试这个:

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

以下是在Python中工作的示例:此示例将内联返回结果。

 from pymongo import MongoClient from bson.code import Code mapper = Code(""" function() { for (var key in this) { emit(key, null); } } """) reducer = Code(""" function(key, stuff) { return null; } """) distinctThingFields = db.things.map_reduce(mapper, reducer , out = {'inline' : 1} , full_response = True) ## do something with distinctThingFields['results'] 

您可以在3.4.4版本中使用新的$ objectToArrray进行聚合,将所有的顶级键值对转换为文档数组,然后用$addToSet$unwind$group $addToSet为整个集合中的不同键。

用于引用顶级文档的$ ROOT 。

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

您可以使用下面的查询获取单个文档中的密钥。

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

这对我来说很好:

 var arrayOfFieldNames = []; var items = db.NAMECOLLECTION.find(); while(items.hasNext()) { var item = items.next(); for(var index in item) { arrayOfFieldNames[index] = index; } } for (var index in arrayOfFieldNames) { print(index); } 

我试图写在nodejs,并最终想出了这个:

 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'); }); }); 

阅读新创build的集合“allFieldNames”后,将其删除。

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

我稍微扩展了Carlos LM的解决scheme,因此更加详细。

模式示例:

 var schema = { _id: 123, id: 12, t: 'title', p: 4.5, ls: [{ l: 'lemma', p: { pp: 8.9 } }, { l: 'lemma2', p: { pp: 8.3 } } ] }; 

input到控制台中:

 var schemafy = function(schema, i, limit) { var i = (typeof i !== 'undefined') ? i : 1; var limit = (typeof limit !== 'undefined') ? limit : false; var type = ''; var array = false; for (key in schema) { type = typeof schema[key]; array = (schema[key] instanceof Array) ? true : false; if (type === 'object') { print(Array(i).join(' ') + key+' <'+((array) ? 'array' : type)+'>:'); schemafy(schema[key], i+1, array); } else { print(Array(i).join(' ') + key+' <'+type+'>'); } if (limit) { break; } } } 

跑:

 schemafy(db.collection.findOne()); 

产量

 _id <number> id <number> t <string> p <number> ls <object>: 0 <object>: l <string> p <object>: pp <number> 

我有一个更简单的工作…

你可以做的是插入数据/文件到你的主要集合“东西”,你必须在1个独立的集合中插入属性可以说“things_attributes”。

所以每次插入“东西”时,如果有任何新密钥存在于文档中,并再次重新插入,则可以从“things_attributes”中获取该文档的值与新文档密钥的值。

因此,things_attributes将只有一个唯一的密钥文件,您可以通过使用findOne()

 var schematodo = db.[collection].findOne(); for (var key in schematodo) { print (key) ; }