集計
Overview
このガイドでは、Java ドライバーを使用して集計操作を実行する方法について説明します。
集計操作により MongoDB コレクション内のデータが処理され、計算結果が返されます。クエリ API の一部である MongoDB 集計フレームワークは、データ処理パイプラインの概念をモデル化したものです。ドキュメントは 1 つ以上のステージで構成されるパイプラインに投入され、そこで集計結果に変換されます。
集計操作は自動車工場に似ています。工場内の組立ラインには、ドリルや溶接機のような、特定の作業をするための専用工具を備えた組立ステーションがあります。未加工のパーツが工場に搬入され、組立ラインで完成品に加工、組み立てられます。
集計パイプラインは組み立てライン、集計ステージは組み立てステーション、演算子式は専用ツールです。
集計操作と検索操作の比較
検索操作を使用して、次のアクションを実行できます。
何のドキュメントを返すかを選ぶ
返すアイテムフィールドの選択
結果を並べ替える
集計操作を使用して、次のアクションを実行できます。
検索操作の実行
フィールドの名前を変更する
フィールドを計算する
データを要約する
値をグループ化する
集計操作には、次のように留意する必要がある制限がいくつかあります。
返されるドキュメントは、 16メガバイトのBSON ドキュメント サイズ 制限に違反していない必要があります。
パイプライン ステージには、デフォルトで100 MB のメモリ制限があります。 必要に応じて、 allowDiskUse を使用してこの制限を超えることができます 使用して複数のドキュメントを挿入できます。
参考文献
実行可能な例
クラスのインポート
「AggTour.java
」という新しい Java ファイルを作成し、次のインポート用ステートメントを含めます。
import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import com.mongodb.ExplainVerbosity; import com.mongodb.client.model.Accumulators; import com.mongodb.client.model.Aggregates; import com.mongodb.client.model.Filters; import com.mongodb.client.model.Projections; import org.bson.Document; import org.bson.json.JsonWriterSettings; import java.util.Arrays; import java.util.List;
MongoDB 配置への接続
public class AggTour { public static void main(String[] args) { // Replace the uri string with your MongoDB deployment's connection string String uri = "<connection string>"; MongoClient mongoClient = MongoClients.create(uri); MongoDatabase database = mongoClient.getDatabase("aggregation"); MongoCollection<Document> collection = database.getCollection("restaurants"); // Paste the aggregation code here } }
Tip
MongoDB への接続の詳細については、「接続ガイド」を参照してください。
サンプル データの挿入
collection.insertMany(Arrays.asList( new Document("name", "Sun Bakery Trattoria").append("contact", new Document().append("phone", "386-555-0189").append("email", "SunBakeryTrattoria@example.org").append("location", Arrays.asList(-74.0056649, 40.7452371))).append("stars", 4).append("categories", Arrays.asList("Pizza", "Pasta", "Italian", "Coffee", "Sandwiches")), new Document("name", "Blue Bagels Grill").append("contact", new Document().append("phone", "786-555-0102").append("email", "BlueBagelsGrill@example.com").append("location", Arrays.asList(-73.92506, 40.8275556))).append("stars", 3).append("categories", Arrays.asList("Bagels", "Cookies", "Sandwiches")), new Document("name", "XYZ Bagels Restaurant").append("contact", new Document().append("phone", "435-555-0190").append("email", "XYZBagelsRestaurant@example.net").append("location", Arrays.asList(-74.0707363, 40.59321569999999))).append("stars", 4).append("categories", Arrays.asList("Bagels", "Sandwiches", "Coffee")), new Document("name", "Hot Bakery Cafe").append("contact", new Document().append("phone", "264-555-0171").append("email", "HotBakeryCafe@example.net").append("location", Arrays.asList(-73.96485799999999, 40.761899))).append("stars", 4).append("categories", Arrays.asList("Bakery", "Cafe", "Coffee", "Dessert")), new Document("name", "Green Feast Pizzeria").append("contact", new Document().append("phone", "840-555-0102").append("email", "GreenFeastPizzeria@example.com").append("location", Arrays.asList(-74.1220973, 40.6129407))).append("stars", 2).append("categories", Arrays.asList("Pizza", "Italian")), new Document("name", "ZZZ Pasta Buffet").append("contact", new Document().append("phone", "769-555-0152").append("email", "ZZZPastaBuffet@example.com").append("location", Arrays.asList(-73.9446421, 40.7253944))).append("stars", 0).append("categories", Arrays.asList("Pasta", "Italian", "Buffet", "Cafeteria")), new Document("name", "XYZ Coffee Bar").append("contact", new Document().append("phone", "644-555-0193").append("email", "XYZCoffeeBar@example.net").append("location", Arrays.asList(-74.0166091, 40.6284767))).append("stars", 5).append("categories", Arrays.asList("Coffee", "Cafe", "Bakery", "Chocolates")), new Document("name", "456 Steak Restaurant").append("contact", new Document().append("phone", "990-555-0165").append("email", "456SteakRestaurant@example.com").append("location", Arrays.asList(-73.9365108, 40.8497077))).append("stars", 0).append("categories", Arrays.asList("Steak", "Seafood")), new Document("name", "456 Cookies Shop").append("contact", new Document().append("phone", "604-555-0149").append("email", "456CookiesShop@example.org").append("location", Arrays.asList(-73.8850023, 40.7494272))).append("stars", 4).append("categories", Arrays.asList("Bakery", "Cookies", "Cake", "Coffee")), new Document("name", "XYZ Steak Buffet").append("contact", new Document().append("phone", "229-555-0197").append("email", "XYZSteakBuffet@example.org").append("location", Arrays.asList(-73.9799932, 40.7660886))).append("stars", 3).append("categories", Arrays.asList("Steak", "Salad", "Chinese")) ));
基本的な集計の例
集計を実行するには、集計ステージのリストを MongoCollection.aggregate()
メソッドに渡します。
Javaドライバーは、集計ステージのビルダを含む集計ヘルパー クラスを提供します。
次の例で集計パイプラインは次のステージを使用しています。
$matchステージを使用して、
categories
配列フィールドに要素Bakery
を含むドキュメントをフィルタリングします。この例では、Aggregates.match
を使って$match
ステージを構築します。$groupステージを使用して、一致するドキュメントを
stars
フィールドでグループ化し、stars
の個別の値ごとにドキュメントの数を蓄積します。
注意
この例で使用されている式は、集計ビルダを使用して作成できます。
collection.aggregate( Arrays.asList( Aggregates.match(Filters.eq("categories", "Bakery")), Aggregates.group("$stars", Accumulators.sum("count", 1)) ) // Prints the result of the aggregation operation as JSON ).forEach(doc -> System.out.println(doc.toJson()));
上記の集計では次の結果が生成されます。
{"_id": 4, "count": 2} {"_id": 5, "count": 1}
このセクションで説明されるメソッドとクラスの詳細については、次の API ドキュメントを参照してください。
集計例の説明
MongoDB が操作を実行する方法に関する情報を表示するには、AggregateIterable
クラスの explain()
メソッドを使用します。explain()
メソッドは実行プランとパフォーマンス統計を返します。実行プランは、MongoDB が操作を完了できる潜在的な方法です。explain()
メソッドには、成功プラン(MongoDB の実行プラン)と拒否プランの両方があります。
Tip
クエリプランと実行統計の詳細については、MongoDB Server マニュアルの「explain の結果」を参照してください。
explain()
メソッドに冗長レベルを渡すことで、説明の詳細度を指定できます。
次のテーブルには、説明のすべての冗長レベルとそのユースケースが示されています。
冗長レベル | ユースケース |
---|---|
ALL_PLANS_EXECUTIONS | MongoDB でクエリを実行するのにどのプランを選んだらよいかを知りたい場合。 |
EXECUTION_STATS | クエリがうまく機能しているかどうかを知りたい場合。 |
QUERY_PLANNER | クエリに問題があり、問題を診断するためにできるだけ多くの情報が必要です。 |
次の例では、実行プランを生成する集計ステージの勝利プランの JSON 表現を出力します。
Document explanation = collection.aggregate( Arrays.asList( Aggregates.match(Filters.eq("categories", "Bakery")), Aggregates.group("$stars", Accumulators.sum("count", 1)) ) ).explain(ExplainVerbosity.EXECUTION_STATS); String winningPlans = explanation .getEmbedded( Arrays.asList("queryPlanner", "winningPlan", "queryPlan"), Document.class ) .toJson(JsonWriterSettings.builder().indent(true).build()); System.out.println(winningPlans);
この例では、$group
ステージが実行プランを生成する唯一のステージであるため、次の出力が生成されます。
{ "stage": "GROUP", "planNodeId": 2, "inputStage": { "stage": "COLLSCAN", "planNodeId": 1, "filter": { "categories": { "$eq": "Bakery" } }, "direction": "forward" } }
このセクションで述べられたトピックについて詳しくは、次のリソースを参照してください。
クエリプランサーバー マニュアル エントリ
ExplainVerbosity APIドキュメント
explain() APIドキュメント
AggregateIterable API ドキュメント
集計式の例
Java ドライバーは、$group
で使用するためのアキュムレータ式のビルダを提供します。他のすべての式は、JSON 形式または互換性のあるドキュメント形式で宣言する必要があります。
Tip
次のいずれかの例の構文によって、 $arrayElemAt式が定義されます。
「カテゴリ」の前に $
が付いている場合、入力ドキュメントの categories
フィールドを使用して、これがフィールド パスであることを MongoDB に伝えています。
new Document("$arrayElemAt", Arrays.asList("$categories", 0))
Document.parse("{ $arrayElemAt: ['$categories', 0] }")
あるいは、Aggregation Expression Operations API を使って式を構築することもできます。詳細については、「集計式操作」を参照してください。
次の例では、集計パイプラインは $project
ステージとさまざまな Projections
を使用して、name
フィールドと、値が categories
フィールドの最初の要素である計算フィールド firstCategory
を返します。
collection.aggregate( Arrays.asList( Aggregates.project( Projections.fields( Projections.excludeId(), Projections.include("name"), Projections.computed( "firstCategory", new Document( "$arrayElemAt", Arrays.asList("$categories", 0) ) ) ) ) ) ).forEach(doc -> System.out.println(doc.toJson()));
上記の集計では次の結果が生成されます。
{"name": "456 Cookies Shop", "firstCategory": "Bakery"} {"name": "Sun Bakery Trattoria", "firstCategory": "Pizza"} {"name": "456 Steak Restaurant", "firstCategory": "Steak"} {"name": "Blue Bagels Grill", "firstCategory": "Bagels"} {"name": "XYZ Steak Buffet", "firstCategory": "Steak"} {"name": "Hot Bakery Cafe", "firstCategory": "Bakery"} {"name": "Green Feast Pizzeria", "firstCategory": "Pizza"} {"name": "ZZZ Pasta Buffet", "firstCategory": "Pasta"} {"name": "XYZ Coffee Bar", "firstCategory": "Coffee"} {"name": "XYZ Bagels Restaurant", "firstCategory": "Bagels"}
このセクションで説明されるメソッドとクラスの詳細については、次の API ドキュメントを参照してください。