集計
Overview
このガイドでは、MongoDB Java ドライバーで集計操作を使用する方法を学習できます。
集計操作により MongoDB コレクション内のデータが処理され、計算結果が返されます。 クエリ API の一部である MongoDB の集計パイプラインは、データ処理パイプラインの概念をモデル化したものです。 ドキュメントは、ドキュメントを集計結果に変換するマルチステージのパイプラインに入力されます。
集計の別の方法は、自動車工場に似ています。 自動車工場内には組立ラインがあり、ドリルや溶接機のような、特定の作業をするための専用工具を備えた組立ステーションです。 未加工のパーツが工場に搬入され、完成品に加工、組み立てられます。
集計パイプラインは組み立てライン、集計ステージは組み立てステーション、演算子式は専用ツールです。
集計操作と検索操作の比較
find
操作を使用すると、次のことが可能になります。
何のドキュメントを返すかを選ぶ
返す項目フィールドの選択
結果を並べ替える
aggregation
操作を使用すると、次のことが可能になります。
すべての
find
操作を実行するフィールドの名前を変更する
フィールドを計算する
データを要約する
値をグループ化する
集計操作には、次のように留意する必要がある制限がいくつかあります。
返されるドキュメントは、 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 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 uri>"; MongoClient mongoClient = MongoClients.create(uri); MongoDatabase database = mongoClient.getDatabase("aggregation"); MongoCollection<Document> collection = database.getCollection("restaurants"); // aggregation here } }
データの挿入
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 が実行されたプラン)と拒否されたプランの両方を提供します。
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); List<Document> stages = explanation.get("stages", List.class); List<String> keys = Arrays.asList("queryPlanner", "winningPlan"); // Prints the JSON representation of the winning execution plans for (Document stage : stages) { Document cursorStage = stage.get("$cursor", Document.class); if (cursorStage != null) { System.out.println(cursorStage.getEmbedded(keys, Document.class).toJson()); } }
上記のコード スニペットでは、次の出力が生成されます。
{ "stage": "PROJECTION_SIMPLE", "transformBy": {"stars": 1, "_id": 0}, "inputStage": { "stage": "COLLSCAN", "filter": { "categories": {"$eq":"bakery"}}, "direction": "forward"}}
このセクションで述べられたトピックについて詳しくは、次のリソースを参照してください。
クエリプランサーバー マニュアル エントリ
ExplainVerbosity APIドキュメント
explain() APIドキュメント
AggregateIterable API ドキュメント
集計式の例
Java ドライバーは、$group
で使用するためのアキュムレータ式のビルダを提供します。他のすべての式は、JSON 形式または互換性のあるドキュメント形式で宣言する必要があります。
Tip
次のいずれかの例の構文によって、 $arrayElemAt式が定義されます。
「カテゴリ」の前に$
が付いている場合、入力ドキュメントの「カテゴリ」フィールドを使用して、これがフィールド パスであることを MongoDB に伝えています。
new Document("$arrayElemAt", Arrays.asList("$categories", 0))
Document.parse("{ $arrayElemAt: ['$categories', 0] }")
次の例では、集計パイプラインは $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 ドキュメントを参照してください。