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