2010-02-19 2324 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的列表,請考慮運行下面的總管道:

​​