1。概要
このチュートリアルでは、MongoDBJavaドライバーを使用したMongoDBAggregationフレームワークについて詳しく説明します。 。
まず、集約の概念的な意味を確認してから、データセットを設定します。最後に、Aggregatesビルダーを使用したさまざまな集計手法の実際の動作を確認します 。
2。アグリゲーションとは何ですか?
集計はMongoDBで使用され、データを分析してそこから意味のある情報を導き出します 。
これらは通常、さまざまなステージで実行され、ステージはパイプラインを形成します。つまり、あるステージの出力が次のステージへの入力として渡されます。
最も一般的に使用されるステージは、次のように要約できます。
ステージ | SQLと同等 | 説明 |
---|---|---|
プロジェクト | SELECT | 必要なフィールドのみを選択し、派生フィールドの計算とコレクションへの追加にも使用できます |
一致 | 場所 | 指定された基準に従ってコレクションをフィルタリングします |
グループ | グループ化 | 指定された基準(カウント、合計など)に従って入力を収集し、個別のグループごとにドキュメントを返します |
並べ替え | 注文者 | 結果を特定のフィールドの昇順または降順で並べ替えます |
カウント | カウント | コレクションに含まれるドキュメントをカウントします |
制限 | 制限 | コレクション全体を返すのではなく、結果を指定された数のドキュメントに制限します |
out | SELECT INTO NEW_TABLE | 結果を名前付きコレクションに書き込みます。この段階は、パイプラインの最後としてのみ受け入れられます |
各集計ステージに相当するSQLが上に含まれているので、SQLの世界でこの操作が何を意味するのかがわかります。
これらすべての段階のJavaコードサンプルをまもなく見ていきます。しかしその前に、データベースが必要です。
3。データベースのセットアップ
3.1。データセット
データベース関連のことを学ぶための最初のそして最も重要な要件は、データセット自体です!
このチュートリアルでは、世界のすべての国に関する包括的な情報を提供する、公開されているRESTfulAPIエンドポイントを使用します。 このAPIは、便利なJSON形式で国の多くのデータポイントを提供します 。分析で使用するフィールドの一部は次のとおりです。
- 名前 –国の名前。たとえば、アメリカ合衆国
- alpha3Code –国名のショートコード。たとえば、 IND (インドの場合)
- 地域 –その国が属する地域。たとえば、ヨーロッパ
- エリア –国の地理的領域
- 言語 –配列形式の国の公用語。たとえば、英語
- 境界線 –近隣諸国の alpha3Codeの配列 s
それでは、このデータをMongoDBデータベースのコレクションに変換する方法を見てみましょう。 。
3.2。 MongoDBへのインポート
まず、 APIエンドポイントをヒットして、すべての国を取得し、応答をローカルでJSONファイルに保存する必要があります。 。次のステップは、 mongoimportを使用してMongoDBにインポートすることです。 コマンド:
mongoimport.exe --db <db_name> --collection <collection_name> --file <path_to_file> --jsonArray
インポートが成功すると、250のドキュメントを含むコレクションが得られます。
4。 Javaでの集約サンプル
基盤がカバーされたので、すべての国について持っているデータからいくつかの意味のある洞察を導き出すに取り掛かりましょう。 。この目的のために、いくつかのJUnitテストを使用します。
ただし、その前に、データベースに接続する必要があります。
@BeforeClass
public static void setUpDB() throws IOException {
mongoClient = MongoClients.create();
database = mongoClient.getDatabase(DATABASE);
collection = database.getCollection(COLLECTION);
}
以下のすべての例では、 Aggregatesを使用します MongoDBJavaドライバーによって提供されるヘルパークラス。
スニペットを読みやすくするために、静的インポートを追加できます:
import static com.mongodb.client.model.Aggregates.*;
4.1。 一致 およびカウント
まず、簡単なことから始めましょう。以前、データセットには言語に関する情報が含まれていることを説明しました。
ここで、英語が公用語である世界の国の数を確認したいとします :
@Test
public void givenCountryCollection_whenEnglishSpeakingCountriesCounted_thenNinetyOne() {
Document englishSpeakingCountries = collection.aggregate(Arrays.asList(
match(Filters.eq("languages.name", "English")),
count())).first();
assertEquals(91, englishSpeakingCountries.get("count"));
}
ここでは、集計パイプラインで2つのステージを使用しています: match およびカウント 。
まず、コレクションを除外して、英語を含むドキュメントのみに一致させます。 言語 分野。これらのドキュメントは、次の段階であるカウントの入力となる一時的または中間的なコレクションとして想像できます。 これにより、前の段階のドキュメントの数がカウントされます。
このサンプルで注意すべきもう1つのポイントは、メソッド firstの使用です。 。最終段階の出力がわかっているので、 count 、は単一のレコードになります。これは、結果として得られる唯一のドキュメントを抽出するための保証された方法です。
4.2。 グループ (合計 )および並べ替え
この例では、最大数の国を含む地理的地域を見つけることを目的としています。 :
@Test
public void givenCountryCollection_whenCountedRegionWise_thenMaxInAfrica() {
Document maxCountriedRegion = collection.aggregate(Arrays.asList(
group("$region", Accumulators.sum("tally", 1)),
sort(Sorts.descending("tally")))).first();
assertTrue(maxCountriedRegion.containsValue("Africa"));
}
明らかなように、グループを使用しています および並べ替え ここで私たちの目的を達成するために 。
まず、合計を累積して、各地域の国の数を収集します。 変数tally。でのそれらの出現の これにより、ドキュメントの中間コレクションが得られます。各フィールドには、地域とその国の集計という2つのフィールドが含まれています。次に、降順で並べ替え、最初のドキュメントを抽出して、最大の国の地域を示します。
4.3。 並べ替え 制限 およびout
それでは、 sortを使用しましょう 、制限 およびout 地域ごとに7つの最大の国を抽出し、それらを新しいコレクションに書き込みます :
@Test
public void givenCountryCollection_whenAreaSortedDescending_thenSuccess() {
collection.aggregate(Arrays.asList(
sort(Sorts.descending("area")),
limit(7),
out("largest_seven"))).toCollection();
MongoCollection<Document> largestSeven = database.getCollection("largest_seven");
assertEquals(7, largestSeven.countDocuments());
Document usa = largestSeven.find(Filters.eq("alpha3Code", "USA")).first();
assertNotNull(usa);
}
ここでは、最初に、指定されたコレクションをarea。の降順で並べ替えました。 次に、 Aggregates#limitを使用しました 結果を7つのドキュメントのみに制限する方法。最後に、 outを使用しました このデータをlargest_sevenと呼ばれる新しいコレクションに逆シリアル化するステージ 。このコレクションは、他のコレクションと同じように使用できるようになりました。たとえば、検索などです。 USAが含まれている場合。
4.4。 プロジェクト、グループ(最大)、一致
最後のサンプルでは、もっとトリッキーなことを試してみましょう。 各国が他の国と共有している国境の数と、そのような最大数を調べる必要があるとしましょう 。
これで、データセットに境界線があります。 alpha3Codeをリストする配列であるフィールド ■国のすべての国境を接する国については、しかし、直接カウントを与えるフィールドはありません。 したがって、 borderingCountriesの数を導出する必要があります。 プロジェクトを使用する :
@Test
public void givenCountryCollection_whenNeighborsCalculated_thenMaxIsFifteenInChina() {
Bson borderingCountriesCollection = project(Projections.fields(Projections.excludeId(),
Projections.include("name"), Projections.computed("borderingCountries",
Projections.computed("$size", "$borders"))));
int maxValue = collection.aggregate(Arrays.asList(borderingCountriesCollection,
group(null, Accumulators.max("max", "$borderingCountries"))))
.first().getInteger("max");
assertEquals(15, maxValue);
Document maxNeighboredCountry = collection.aggregate(Arrays.asList(borderingCountriesCollection,
match(Filters.eq("borderingCountries", maxValue)))).first();
assertTrue(maxNeighboredCountry.containsValue("China"));
}
その後、前に見たように、グループ化します maxを見つけるために投影されたコレクション borderingCountriesの値 。ここで指摘することの1つは、 max アキュムレータは、数値として最大値を提供します 、ドキュメント全体ではありません 最大値を含みます。 一致を実行する必要があります 目的のドキュメントを除外します さらに操作を実行する場合。