2010-02-19 2307 views
246

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

例如,从这个:

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

我想获得的唯一键:

type, egg, hello 

回答

261

您可以用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" 
}) 

然后运行对所得到的集合进行区分以便找到所有关键字:

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

你好!我刚刚发布了一个后续问题,询问如何使该代码片段即使在数据结构更深层次的关键字中也能正常工作(http://stackoverflow.com/questions/2997004/using-map-reduce-for -mapping最性质-IN-A-集合)。 – 2010-06-08 14:53:22

+1

@kristina:在* things *集合上使用这个键时,我怎么可能获得全部*东西*。它看起来与历史机制有关,因为我得到*过去曾修改的东西* – Shawn 2011-09-26 02:54:09

+0

为什么上述方法比使用Python对外部核对键时花费的时间更长? – MFB 2012-08-23 06:06:00

169

随着Kristina's answer为灵感,我创建了一个名为品种的开源工具,它正是这样做的:https://github.com/variety/variety

+13

这是一个很棒的工具,恭喜。它完全符合问题的要求,并且可以配置极限,深度等。 – 2012-06-10 20:35:08

+1

不能工作了:( – Artem 2016-06-25 18:52:54

+0

刚刚试过它,它的工作 – 2017-07-26 14:29:14

21

试试这个:

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

不正确的答案,因为这只能输出一个集合中的单个文档的字段 - 其他人可能都有完全不同的键 – 2014-03-31 23:41:42

+13

它仍然是我最有用的答案, – 2014-07-31 16:13:55

+7

它没有用,如果它给你错误的答案,它有用吗? – Zlatko 2015-06-27 07:48:19

-3

我有1简单的解决办法...

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

因此,每次插入“东西”时,如果有任何新密钥将其附加到该文档中并再次重新插入,则可以从“things_attributes”获得该文档的值与新文档关键字的比较结果。

所以things_attributes将只有1唯一键的文件,该文件时,你永远需要使用findOne就可以轻松搞定()

-1

我伸出卡洛斯LM的解决方案了一点,所以它更详尽。一个模式的

实施例:

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

类型到控制台:

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> 
+3

他的回答是错误的,你建立在它之上。整个问题的关键是输出所有文档的所有字段,而不是每个下一个字段可能有不同字段的第一个文档。 – 2014-03-31 23:43:03

7

以下是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'] 
9

使用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() 
) 
+1

我已经发现这个工作,但它与原始mongod查询相比效率如何? – 2016-01-27 19:47:43

+0

我相当肯定,这是相当直接在Mongodb做这个效率非常低 – ifischer 2018-01-05 16:39:10

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

这是一个坏的答案的重复! – yonatan 2016-01-07 08:59:52

1

这对我工作得很好:

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

如果你的目标集合不是太大,你可以试试这个下蒙戈壳客户端:

var allKeys = {}; 

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

allKeys; 
+0

这里如何我可以给regExp特定的键如果我想看? – 2017-03-24 05:41:25

+0

@ TB.M你可以试试这个: db.configs.find()。forEach(function(doc){Object.keys(doc).forEach(function(key){if(/YOURREGEXP/.test(key) ){allKeys [key] = 1}})}); – 2017-03-27 04:22:08

+0

这里测试的含义是什么?你能解释一下吗? – 2017-03-27 06:03:23

15

您可以使用新$objectToArrray聚集3.4.4版本CONV将所有顶级密钥&值对分配到文档数组中,然后使用$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"}} 
]) 
+5

这真的是最好的答案。在不涉及其他编程语言或软件包的情况下解决问题,并与支持聚合框架的所有驱动程序(甚至Meteor!)配合使用 – 2017-11-16 21:48:46

0

我试图在对的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'); 
     }); 
}); 

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

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

一个清理和可重复使用的解决方案使用pymongo:

from pymongo import MongoClient 
from bson import Code 

def get_keys(db, collection): 
    client = MongoClient() 
    db = client[db] 
    map = Code("function() { for (var key in this) { emit(key, null); } }") 
    reduce = Code("function(key, stuff) { return null; }") 
    result = db[collection].map_reduce(map, reduce, "myresults") 
    return result.distinct('_id') 

用法:

get_keys('dbname', 'collection') 
>> ['key1', 'key2', ... ] 
0

要获得所有按键减去_id的列表,请考虑运行下面的总管道:

​​