Overview
このガイドでは、MongoDB との照合を使用して、クエリまたは集計操作の結果を string 値で並べ替える方法を説明します。 照合は、特定の言語とロケールに適用される文字の順序付けとマッチング ルールのセットです。
照合の詳細については、このガイドの次のセクションを参照してください。
重要
プロジェクトリ アクター ライブラリ
このガイドでは、プロジェクト Reactive ライブラリを使用して、 Java Reactive Streams ドライバー メソッドによって返された Publisher インスタンスを消費します。Project Reactive ライブラリとその使用方法の詳細については、React ドキュメントの使用開始を参照してください。このガイドでは Project React ライブラリ メソッドをどのように使用しているかについて詳しくは、 「 MongoDBへのデータの書込み 」ガイドを参照してください。
MongoDB の照合
MongoDB は、デフォルトで バイナリ照合 を使用して string をソートします。バイナリ照合では、ASCII 標準 文字値を使用して string を比較および順序付けます。特定の言語とロケールには、ASCII 文字値とは異なる特定の文字順序付け規則があります。
たとえば、カナダフランス語では、先行するすべての文字が同じ場合、右端のアクセント記号(発音区別符号)によって string の順序が決まります。 次のカナダフランス語の単語について考えてみます。
コピー
coté
côte
côté
バイナリ照合を使用する場合、MongoDB はそれらを次の順序でソートします。
cote coté côte côté
カナダ フランス語の照合を使用する場合、MongoDB はそれらを次の順序でソートします。
cote côte coté côté
照合の指定方法
MongoDB は、ほとんどの CRUD 操作と集計で照合をサポートしています。サポートされている操作の完全なリストについては、MongoDB Server マニュアルの「照合をサポートする操作」を参照してください。
ロケール コードとオプションのバリアントを次の string 形式で指定できます。
"<locale code>@collation=<variant code>"
次の例では、"de"ロケール コードと"phonebook"バリアント コードを指定します。
"de@collation=phonebook"
バリアントを指定しない場合は、ロケール コードのみを使用します。
サポートされているロケールの完全なリストについては、MongoDB Server マニュアルの「サポートされている言語とロケール」を参照してください。
次のセクションでは、MongoDB で照合を適用するさまざまな方法を説明します。
コレクション
コレクションの作成時にのみ、デフォルトの照合をコレクションに設定できます。ただし、既存のコレクションの新しいインデックスで照合を指定できます。コレクションをスキャンするすべてのサポートされている操作は、デフォルトの照合を適用します。詳細については、このガイドのインデックスセクションを参照してください。
次の例は、itemsという新しいコレクションを作成するときに"en_US"ロケール照合を指定する方法を示しています。
Mono.from(database.createCollection( "items", new CreateCollectionOptions().collation( Collation.builder().locale("en_US").build()))) .block();
照合が正常に作成されたかどうかを確認するには、次のように、そのコレクションのインデックスのリストを取得します。
List<Document> indexes = Flux.from(itemsCollection.listIndexes()) .collectList().block(); if (indexes != null) { indexes.forEach(idx -> System.out.println(idx.toJson())); }
上記のコードの出力には、次の内容が含まれている必要があります。
{ ... "collation": { "locale": "en_US", ... } ... }
Index
コレクションに新しいインデックスを作成するときに照合を指定できます。インデックスはドキュメントを指定された順序で保存するため、クエリ中のインメモリソートの必要がなくなります。インデックスを使用するには、操作ではインデックスで指定されたと同じ照合を使用し、そのインデックスでカバーされている必要があります。
次の例では、"en_US" ロケール照合で "name" フィールドにインデックスを昇順で作成する方法を示しています。
IndexOptions idxOptions = new IndexOptions(); idxOptions.collation(Collation.builder().locale("en_US").build()); Mono.from(itemsCollection.createIndex( Indexes.ascending("name"), idxOptions)).block();
照合が正常に作成されたかどうかを確認するには、次のように、そのコレクションのインデックスのリストを取得します。
List<Document> indexes = Flux.from(itemsCollection.listIndexes()) .collectList().block(); if (indexes != null) { indexes.forEach(idx -> System.out.println(idx.toJson())); }
上記のコードの出力には、次の内容が含まれている必要があります。
{ ... "collation": { "locale": "en_US", ... } ... }
次の例は、同じ照合を指定し、前の例で作成したインデックスによってカバーされる操作を示しています。
FindPublisher<Document> indexPublisher = itemsCollection.find() .collation(Collation.builder().locale("en_US").build()) .sort(Sorts.ascending("name")); Flux.from(indexPublisher) .doOnNext(doc -> System.out.println(doc.toJson())) .blockLast();
操作
サポートされている操作に新しい照合を渡すことで、デフォルトの照合を上書きできます。ただし、インデックスがない場合、クエリはインメモリでのソートを実行しますが、これはインデックスされた照合を使用するよりも低速です。インデックスでカバーされていないソート操作の欠点の詳細については、MongoDB Server マニュアルの「インデックスを使用してクエリ結果をソートするを参照してください。
次の例は、次の特性を持つクエリ操作を示しています。
参照先のコレクションには、デフォルトの
"en_US"照合インデックスがあります。これは、コレクションセクションで指定されたものと同様です。クエリではアイスランド語 (
"is") の照合が指定されています。これはインデックス照合と異なるため、クエリではインデックスが使用されず、インメモリソートが実行されます。
FindPublisher<Document> customPublisher = itemsCollection.find() .collation(Collation.builder().locale("is").build()) .sort(Sorts.ascending("name")); Flux.from(customPublisher) .doOnNext(doc -> System.out.println(doc.toJson())) .blockLast();
照合をサポートしないインデックスの種類
MongoDB のほとんどのインデックス タイプは照合をサポートしています。ただし、次のタイプはバイナリ比較のみをサポートしており、照合はサポートしていません。
Collation Options
このセクションでは、さまざまな照合オプションと、順序付けと一致の動作をさらに絞り込むための指定方法について説明します。
照合オプション | 説明 |
|---|---|
ロケール | 必須。言語とバリアントの ICU ロケールコード。 |
バックワード | string の末尾から始めて分音記号を考慮するかどうかを指定します。 |
大文字と小文字の区別 | 大文字と小文字を別の値として考慮するかどうかを指定します。 |
代替 | スペースと句読点を考慮するかどうかを指定します。 |
caseFirst | 大文字と小文字のどちらを先に考慮するかを指定します。 |
Max Vvariable | 空白を無視するか、空白と句読点の両方を無視するかを指定します。この設定は、代替設定が「shifted」の場合にのみ有効です。 |
強度 | ICU 比較レベルを指定します。デフォルト値は "tertiary" です。各レベルの詳細については、ICU 比較レベルを参照してください。 |
正規化 | 必要に応じて、テキストに対してユニコード正規化を実行するかどうかを指定します。ユニコード正規化の詳細については、「ユニコード正規化形式」を参照してください。 |
numericOrdering | 照合順ではなく、数値に従って数字を順序付けるかどうかを指定します。 |
Collation.Builderクラスを使用して、前述の照合オプションの値を指定できます。次の例に示すように、build()メソッドを呼び出してCollationオブジェクトを構築します。
Collation.builder() .caseLevel(true) .collationAlternate(CollationAlternate.SHIFTED) .collationCaseFirst(CollationCaseFirst.UPPER) .collationMaxVariable(CollationMaxVariable.SPACE) .collationStrength(CollationStrength.SECONDARY) .locale("en_US") .normalization(false) .numericOrdering(true) .build();
対応するメソッドとパラメータの詳細については、照合.Builder の API ドキュメントを参照してください。
照合の例
このセクションには、照合をサポートする MongoDB 操作の使用方法の例が含まれています。各例では、次のドキュメント コレクションから開始すると仮定します。
{ "_id" : 1, "first_name" : "Klara" } { "_id" : 2, "first_name" : "Gunter" } { "_id" : 3, "first_name" : "Günter" } { "_id" : 4, "first_name" : "Jürgen" } { "_id" : 5, "first_name" : "Hannah" }
次の例では、"de@collation=phonebook" ロケールとバリアント照合が使用されています。照合の "de" パートではドイツ語ロケールが指定され、"collation=phonebook" パートではバリアントが指定されます。"de" ロケール照合には、最初の文字の大文字化によって識別される固有名詞の優先順位付けのルールが含まれています。"collation=phonebook" バリアントでは、アンシングソートでウムラウトが付いた文字は、ウムラウトが付いていない同じ文字の前に配置されます。
find() と sort() の例
次の例は、コレクションからソートされた結果を取得するときに照合を適用する方法を示しています。この操作を実行するには、find() を**例**コレクションで呼び出し、collation() メソッドと sort() メソッドをチェーンして、結果を受信する順序を指定します。
FindPublisher<Document> findPublisher = phonebookCollection.find() .collation(Collation.builder() .locale("de@collation=phonebook").build()) .sort(Sorts.ascending("first_name")); Flux.from(findPublisher) .doOnNext(doc -> System.out.println(doc.toJson())) .blockLast();
この操作をサンプル コレクションに対して実行すると、出力は次のようになります。
{"_id": 3, "first_name": "Günter"} {"_id": 2, "first_name": "Gunter"} {"_id": 5, "first_name": "Hannah"} {"_id": 4, "first_name": "Jürgen"} {"_id": 1, "first_name": "Klara"}
このセクションで説明されるメソッドとクラスの詳細については、次の API ドキュメントを参照してください。
findOneAndUpdate() の例
次の例では、FindOneAndUpdateOptions オブジェクトをインスタンス化してパラメーターとして渡すことで、findOneAndUpdate() 操作で照合を指定しています。この例では、次の操作を実行します。
昇順で「Gunter」に先行する例 コレクション内の最初のドキュメントを検索する。
"de@collation=phonebook"照合を含む操作のオプションを設定します。値が「true」である新しいフィールド「検証済み」を追加します。
更新されたドキュメントを検索して印刷します。
Document updatedDoc = Mono.from( phonebookCollection.findOneAndUpdate( Filters.lt("first_name", "Gunter"), Updates.set("verified", true), new FindOneAndUpdateOptions() .collation(Collation.builder() .locale("de@collation=phonebook") .build()) .sort(Sorts.ascending("first_name")) .returnDocument(ReturnDocument.AFTER))) .block(); if (updatedDoc != null) { System.out.println("Updated document: " + updatedDoc.toJson()); }
"Günter" は、昇順の de@collation=phonebook 照合を使用して、辞書的に "Gunter" より前にあるため、上記の操作は次のドキュメントを返します。
Updated document: {"_id": 3, "first_name": "Günter", "verified": true}
このセクションで説明されるメソッドとクラスの詳細については、次の API ドキュメントを参照してください。
findOneAndDelete() の例
次の例では、FindOneAndDeleteOptions オブジェクトをインスタンス化し、パラメーターとして渡すことによって、findOneAndDelete() 操作で数値順の照合を指定します。コレクションには、次のドキュメントが含まれます。
{ "_id" : 1, "a" : "16 apples" } { "_id" : 2, "a" : "84 oranges" } { "_id" : 3, "a" : "179 bananas" }
照合では、 locale オプションを "en" に、 numericOrdering オプションを "true" に設定して、数値に基づいて文字列を並べ替えます。
Document deletedDoc = Mono.from( numericalCollection.findOneAndDelete( Filters.gt("a", "100"), new FindOneAndDeleteOptions() .collation(Collation.builder() .locale("en") .numericOrdering(true) .build()) .sort(Sorts.ascending("a")))) .block(); if (deletedDoc != null) { System.out.println("Deleted document: " + deletedDoc.toJson()); }
上記の操作を実行すると、出力は次のようになります。
Deleted document: {"_id": 3, "a": "179 bananas"}
string "179" の数値は 100 より大きいため、前のドキュメントが唯一の一致となります。数値の順序付きではなく、バイナリ照合では "100" が "16" 、 "84" 、 "179" より前にソートされるため、フィルターはすべてのドキュメントに一致します。
このセクションで説明されるメソッドとクラスの詳細については、次の API ドキュメントを参照してください。
集計の例
次の例は、集計操作で照合を指定する方法を示しています。集計を実行するには、MongoCollection オブジェクトで aggregate() メソッドを呼び出します。
集計操作の照合を指定するには、集計操作によって返された AggregatePublisher で collation() メソッドを呼び出します。パイプラインで並べ替え集計ステージを指定して照合を適用します。
次の例では、サンプル コレクションに集計パイプラインを構築し、以下を指定して照合を適用します。
Aggregates.group()を使用してfirst_nameフィールドで各ドキュメントを識別し、その値を結果の_idとして使用するグループ集計ステージ。first_nameフィールドに一致する値のインスタンス数を合計するためのグループステージのアキュムレータ。出力ドキュメントの
_idフィールドに対する昇順並べ替え。ドイツ語のロケールと、アクセントやウムラウトを無視する照合強度を指定する照合オブジェクト。
Bson groupStage = Aggregates.group( "$first_name", Accumulators.sum("nameCount", 1)); Bson sortStage = Aggregates.sort(Sorts.ascending("_id")); AggregatePublisher<Document> aggregatePublisher = phonebookCollection .aggregate(Arrays.asList(groupStage, sortStage)) .collation(Collation.builder() .locale("de") .collationStrength(CollationStrength.PRIMARY) .build()); Flux.from(aggregatePublisher) .doOnNext(doc -> System.out.println(doc.toJson())) .blockLast();
上記のコードでは、次のドキュメントが出力されます。
{"_id": "Gunter", "nameCount": 2} {"_id": "Hannah", "nameCount": 1} {"_id": "Jürgen", "nameCount": 1} {"_id": "Klara", "nameCount": 1}
このセクションで説明されるメソッドとクラスの詳細については、次の API ドキュメントを参照してください。