MongoDBの集計処理中に文字列を分割する方法
MongoDBで集計処理を行いながら文字列を分割したい場合、mapReduce()メソッドを活用する方法があります。この記事では、実際のコード例を使いながら、コレクション内のドキュメントから氏名を取得し、名前を空白で分割して姓だけを抽出する手順を詳しく解説します。
1. コレクションの作成とドキュメントの挿入
まずは、サンプル用のコレクションを作成し、ドキュメントを挿入します。ここではinsertOne()メソッドを使用して、学生の氏名を含むドキュメントを登録します。
> db.splitString.insertOne({"StudentName":"John Smith"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e0849d925ddae1f53b62206")
}
これでsplitStringコレクションに「John Smith」という氏名を持つドキュメントが1件登録されました。
2. 登録したドキュメントの確認
次に、find()メソッドを使って、コレクション内のすべてのドキュメントを表示して確認します。
> db.splitString.find().pretty();
実行すると、以下のような出力が得られます。
{
"_id" : ObjectId("5e0849d925ddae1f53b62206"),
"StudentName" : "John Smith"
}
3. mapReduce()を使って文字列を分割する
それでは本題の、文字列を分割するクエリを見ていきましょう。map関数の中でJavaScriptのsplit()メソッドを使い、氏名を空白文字(正規表現 /\s/)で分割します。さらにreverse()[0]で配列の最後の要素(つまり姓)を取り出し、toUpperCase()で大文字に変換しています。
> db.splitString.mapReduce(
... function() {
... var StudentLastName = this.StudentName.split(/\s/).reverse()[0].toUpperCase();
...
... emit({ "StudentLastName": StudentLastName, "FirstObjectId": this._id },this);
... },
... function(){},
... { "out": { "inline": 1 } }
... );
このクエリのポイントは以下の通りです。
- map関数:各ドキュメントに対して
this.StudentNameを空白で分割し、末尾の要素(姓)を大文字化して変数に格納します。 - emit()関数:分割・変換した「姓」と元のドキュメントの
_idをキーとして結果を出力します。 - reduce関数:今回は単純な分割処理のみのため、空の関数を指定しています。
- outオプション:
{ "inline": 1 }を指定することで、結果を新しいコレクションに保存せず、その場でインライン表示します。
4. 実行結果の確認
上記のmapReduceを実行すると、以下のような出力が得られます。
{
"results" : [
{
"_id" : {
"StudentLastName" : "SMITH",
"FirstObjectId" : ObjectId("5e0849d925ddae1f53b62206")
},
"value" : {
"_id" : ObjectId("5e0849d925ddae1f53b62206"),
"StudentName" : "John Smith"
}
}
],
"timeMillis" : 32,
"counts" : {
"input" : 1,
"emit" : 1,
"reduce" : 0,
"output" : 1
},
"ok" : 1
}
結果を見ると、_idフィールドにStudentLastNameとして「SMITH」が出力されていることがわかります。元の氏名「John Smith」から姓だけが正しく抽出され、大文字に変換されています。また、countsには入力ドキュメント数(input: 1)、emit回数(emit: 1)、出力数(output: 1)といった統計情報も含まれており、処理の状況を確認できます。
補足:アグリゲーションフレームワークでの代替手段
なお、MongoDB 4.2以降ではmapReduce()は非推奨となっており、最新バージョンでは削除されています。現在の開発では、アグリゲーションパイプラインの$split演算子や$arrayElemAt、$toUpperなどを組み合わせることで、同様の文字列分割処理をより効率的に実現できます。新規プロジェクトでは、アグリゲーションフレームワークの利用を検討することをおすすめします。
-
MongoDBのaggregateで$groupを使って複数の集計結果を一度に取得する方法
MongoDBでは、$facetと$groupを組み合わせることで、1回のaggregateクエリで複数の集計結果を同時に取得できます。この記事では、実際のコード例を通じてその方法を解説します。サンプルコレクションの作成まず、ドキュメントを含むコレクションを作成しましょう。以下のようにinsertOne()メソッドを使ってデータを挿入します。> db.demo765.insertOne( ... { ... Name:John, ... Category:ComputerScience, ... SubjectName:MongoDB,
-
Pythonで文字列を指定サイズ(N文字)ごとに分割する方法
問題の概要 文字列 s と整数 n が与えられたとき、s を n 文字ずつの部分文字列に分割することを考えます。 例えば、入力が s = abcdefghijklmn、n = 4 の場合、出力は [abcd, efgh, ijkl, mn] となります。最後の断片が n 文字に満たない場合でも、残りの文字列がそのまま出力される点に注意してください。 解決のアプローチ この問題は、以下の手順で解くことができます。 インデックス i を 0 で初期化します。 結果を格納するための空のリスト f を用意します。 i が文字列の長さ未満である間、次の処理を繰り返します。 s[i : i+n](イ