MongoDBコレクション内の全キー名を取得する方法|MapReduce・Aggregation・シェルなど状況別に解説

スキーマの検証、フィールド名のタイプミスのデバッグ、設定されるべきではないフィールドの発見などを行うには、まずMongoDBコレクション内にどのようなキーが存在するのかを把握しておく必要があります。
多くのMongoDB-as-a-Service事業者は、UI上で手軽にこれを実現できる機能を提供しています(ObjectRocketもそのひとつです)。また、経験豊富なMongoDBユーザーの多くは、JavaScript向けのMongooseやPython向けのMongoengineといったオブジェクトドキュメントマッパー(ODM)を導入しています。ODMを使えば、アプリケーション向けの一貫性のあるスキーマを構築でき、タイプミスを減らせるだけでなく、型検証によって「整数が入るべきフィールドに誤って文字列を保存してしまう」といったトラブルも防げます。
こうしたサービスやODMを利用していない場合でも、キー情報へアクセスする方法はいくつかあります。本記事では、さまざまな状況に応じてMongoDBコレクション内のすべてのキーを取得するためのベストな手法を紹介します。
前提となるサンプルデータ
まず、次のようなドキュメントを持つコレクションを例に考えてみましょう。
db.activities.insert( { type : ['indoor', 'outdoor' , 'mixed'] } );
db.activities.insert( { activity : 'cycling' } );
db.activities.insert( { activity : 'skiing', location: 'Alpes'} );
db.activities.insert( { equipment : ['paddles','sunglasses'] } );このコレクションから取得したいユニークなキーは次の4つです。
type / activity / equipment / location
方法1:MapReduceを使う
MapReduceを利用すれば、コレクション全体のキーを抽出できます。
mr = db.runCommand({ "mapreduce" : "activities", "map" : function() { for (var key in this) { emit(key, null); } }, "reduce" : function(key, stuff) { return null; }, "out": "activities" + "_keys" })処理が完了したら、生成されたコレクションに対してdistinctコマンドを実行すれば、すべてのキーを取得できます。
db.activities_keys.distinct("_id")サブドキュメント内のユニークなキーを取得したい場合は、map関数内の該当行を次のように書き換えます。
for (var key in this.first_level.second_level.nth_level) { emit(key, null); }方法2:アグリゲーション(Aggregation)を使う
アグリゲーションフレームワークでも同じことが可能です。この方法は、aggregateをサポートするすべてのドライバーで動作します。処理のオーバーヘッドを抑えたい場合は、$sampleや$limitを組み合わせると効果的です。
注意: プライマリ読み取り優先(read preference)で実行するとパフォーマンスに影響が出る可能性があります。セカンダリ読み取り優先での実行を検討してください。
$objectToArray(バージョン3.4.4以降で利用可能)を使ってトップレベルのキーと値のペアをすべてドキュメント配列に変換し、続けて$unwindと$group($addToSet)を組み合わせることで、コレクション全体から重複のないキー一覧を取得できます。
$$ROOTは、トップレベルのドキュメントを参照するための変数です。
db.activities.aggregate([ {"$project":{"arrayofkeyvalue":{"$objectToArray":"$$ROOT"}}}, {"$unwind":"$arrayofkeyvalue"}, {"$group":{"_id":null,"allkeys":{"$addToSet":"$arrayofkeyvalue.k"}}} ])単一ドキュメントのキーを取得する
アグリゲーションを使えば、特定の1件のドキュメントに含まれるキーだけを取得することもできます。
db.activities.aggregate([ {"$project":{"arrayofkeyvalue":{"$objectToArray":"$$ROOT"}}}, {"$project":{"keys":"$arrayofkeyvalue.k"}} ])方法3:mongoシェルを使う
mongoシェルクライアントからなら、次のようにして確認できます。
var allKeys = {}; db.YOURCOLLECTION.find().forEach(function(doc){Object.keys(doc).forEach(function(key){allKeys[key]=1})}); allKeys;方法4:単一ドキュメントの出力フィールドを確認する
コレクション内の1件のドキュメントに含まれるフィールドを出力したい場合(他のドキュメントはまったく異なるキーを持っている可能性があるため)は、次のコマンドが便利です。
doc=db.thinks.findOne(); for (key in doc) print(key);方法5:Python(pymongo)を使う
Pythonでも実現できます。次のコードは、コレクション内のすべてのトップレベルキーの集合(set)を返します。
#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()
)方法6:JavaScript(Node.js)を使う
Node.jsなどのJavaScript環境でも、MapReduceを組み合わせて実装できます。
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);
deleteCollection(db, 'allFieldNames');
})
.catch(function(err) {
res.send(err);
deleteCollection(db, 'allFieldNames');
});
});新しく作成された「allFieldNames」コレクションを読み取った後は、忘れずに削除しましょう。
db.collection("allFieldNames").remove({}, function (err,result) { db.close(); return; });まとめ:目的に合った方法を選ぼう
このように、MongoDBのキーを取得する方法は多数あります。コレクションの規模、使用している言語やドライバー、リアルタイム性の要件などに応じて、最適な手法を選択してください。もしMongoDBの運用・管理に負担を感じていて、「データベース管理よりも開発に集中したい」とお考えであれば、専門家によるきめ細かいサポート付きのマネージドデータベースプラットフォームの活用も検討してみてはいかがでしょうか。当社のデータベースプラットフォームとホワイトグローブサポートは、無料でお試しいただけます。
-
Pythonの辞書からすべてのキーをリストとして取得する方法
Pythonの辞書(dict)からすべてのキーをリストとして取得したい場合、最もシンプルな方法は dict.keys() メソッドを使うことです。このメソッドは辞書内のすべてのキーを含むビューオブジェクトを返すため、list() で囲むことで簡単にリストへ変換できます。keys()メソッドを使う例my_dict = {name: TutorialsPoint, time: 15 years, location: India} key_list = list(my_dict.keys()) print(key_list)出力実行すると、次のような結果が得られます。[name, time, loc
-
MongoDBコレクションの全キー(フィールド名)を取得する方法まとめ
この記事は2019年1月18日にObjectRocket.com/blogで公開された内容をもとにしています。 MongoDB®のコレクションに含まれるすべてのキーを把握することは、スキーマの検証、フィールド名のタイプミスのデバッグ、設定すべきでないフィールドの発見など、さまざまな場面で役立ちます。本記事では、MongoDBコレクション内の全キー名を取得する複数の方法を、状況別にわかりやすく解説します。 まず検討したい:ODMやマネージドサービスの活用 ObjectRocketをはじめとする多くのMongoDB-as-a-Service事業者は、ユーザーインターフェース(UI)上で簡単にキーを