355

MongoDBコレクション内のすべてのキーの名前を取得したいと思います。

たとえば、これから:

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

一意のキーを取得したい:

type, egg, hello
4

23 に答える 23

376

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

次に、結果のコレクションに対して distinct を実行して、すべてのキーを見つけます。

db[mr.result].distinct("_id")
["foo", "bar", "baz", "_id", ...]
于 2010-02-22T00:03:21.037 に答える
223

クリスティーナの答えをインスピレーションとして、まさにこれを行う Variety というオープンソース ツールを作成しました: https://github.com/variety/variety

于 2012-04-28T17:53:52.677 に答える
123

$objectToArrayバージョン3.4.4の新しい集計演算子で集計を使用して、上位のすべてのキーと値のペアをドキュメント配列に変換し、その後に$unwindand$group$addToSet使用して、コレクション全体で個別のキーを取得できます。($$ROOT最上位のドキュメントを参照するために使用します。)

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

次のクエリを使用して、1 つのドキュメント内のキーを取得できます。

db.things.aggregate([
  {"$match":{_id: "<<ID>>"}}, /* Replace with the document's ID */
  {"$project":{"arrayofkeyvalue":{"$objectToArray":"$$ROOT"}}},
  {"$project":{"keys":"$arrayofkeyvalue.k"}}
])
于 2017-04-23T11:45:11.260 に答える
18

ターゲット コレクションが大きすぎない場合は、mongo シェル クライアントでこれを試すことができます。

var allKeys = {};

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

allKeys;
于 2016-12-26T06:38:57.437 に答える
11

パイソンの使用。コレクション内のすべての最上位キーのセットを返します。

#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()
)
于 2014-08-11T09:12:18.383 に答える
9

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']
于 2014-04-25T00:42:24.723 に答える
3

これは私にとってはうまくいきます:

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);
}
于 2016-05-04T14:54:06.473 に答える
0

私はパーティーに遅れていることを知っていますが、Python ですべてのキー (ネストされたものも含む) を見つけるための迅速な解決策が必要な場合は、再帰関数を使用できます。

def get_keys(dl, keys=None):
    keys = keys or []
    if isinstance(dl, dict):
        keys += dl.keys()
        list(map(lambda x: get_keys(x, keys), dl.values()))
    elif isinstance(dl, list):
        list(map(lambda x: get_keys(x, keys), dl))
    return list(set(keys))

次のように使用します。

dl = db.things.find_one({})
get_keys(dl)

ドキュメントに同一のキーがない場合は、次のことができます。

dl = db.things.find({})
list(set(list(map(get_keys, dl))[0]))

しかし、このソリューションは確実に最適化できます。

一般に、このソリューションは基本的に、ネストされた辞書でキーを見つけることを解決しているため、これは mongodb 固有ではありません。

于 2022-01-31T14:14:27.073 に答える
0

この質問が 10 年前のものであることは知っていますが、C# のソリューションはなく、これを理解するのに何時間もかかりました。私は.NETドライバーを使用しておりSystem.Linq、キーのリストを返しています。

var map = new BsonJavaScript("function() { for (var key in this) { emit(key, null); } }");
var reduce = new BsonJavaScript("function(key, stuff) { return null; }");
var options = new MapReduceOptions<BsonDocument, BsonDocument>();
var result = await collection.MapReduceAsync(map, reduce, options);
var list = result.ToEnumerable().Select(item => item["_id"].ToString());
于 2020-04-03T21:20:25.710 に答える
-1

Carlos 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> 
于 2014-03-28T13:37:47.770 に答える
-3

もっと簡単な回避策が1つあります...

できることは、データ/ドキュメントをメイン コレクションの「もの」に挿入するときに、属性を 1 つの別のコレクションに挿入する必要があることです。たとえば、「things_attributes」とします。

そのため、「things」に挿入するたびに、「things_attributes」から取得して、そのドキュメントの値を新しいドキュメント キーと比較します。新しいキーが存在する場合は、そのドキュメントに追加し、再度挿入します。

そのため、things_attributes には一意のキーのドキュメントが 1 つだけあり、findOne() を使用して必要なときにいつでも簡単に取得できます。

于 2014-03-21T11:41:39.757 に答える