0

次のSQLコマンドのようにmongoDBを使用してタイ語フィールドをソートする方法は?

SELECT * FROM employee ORDER BY CONVERT(name USING tis620)
4

2 に答える 2

0

実は方法があります!(ハックですが。)

これが古いスレッドであることは知っていますが、とにかく答えると役立つと思います。

コレクション内のすべてのドキュメントをメモリに格納して並べ替え、必要なウィンドウを返す必要があるため、アプリで並べ替えを実行したくないことは間違いありません。コレクションが膨大な場合、これは非常に非効率的です。データベースはソートを行い、ウィンドウを返します。

しかし、MongoDB はロケールに依存した並べ替えをサポートしていません。問題をどのように解決しますか?魔法は「ソートキー」の概念です。

基本的に、「a」から「z」までの通常の英語/ラテン語のアルファベットがあるとしましょう。あなたがすることは、「a」から「01」、「b」から「02」など、「z」から「26」までのソートキーマッピングを作成することです。つまり、その言語のソート順ですべての文字を数値にマップし、その数値を文字列としてエンコードします。次に、並べ替える文字列をこの種類の並べ替えキーにマップします。たとえば、「abc」は「010203」になります。次に、プロパティの並べ替えキーを使用してドキュメントにプロパティを追加し、プロパティの名前をロケールの名前に追加します。

{
    name: "abc",
    name_en: "010203"
}

プロパティ「name_en」でインデックスを作成するだけで言語「en」でソートし、「name」プロパティの代わりにセレクターと範囲にプレーンな古い英語ベースの MongoDB ソートを使用できるようになりました。

ここで、アルファベットの順序が「abc」ではなく「acb」である別のクレイジーな言語「xx」があるとします。(はい、そのようにラテン アルファベットの順序を台無しにする言語があります!) ソート キーは次のようになります。

{
    name: "abc",
    name_en: "010203",
    name_xx: "010302"
}

あとは、name_en と name_xx にインデックスを作成し、通常の MongoDB ソートを使用して、これらのロケールで正しくソートするだけです。基本的に、追加のプロパティは、異なるロケールでソートするためのプロキシです。

では、これらのマッピングはどこで取得するのでしょうか? 結局のところ、あなたはグローバリゼーションの専門家ではありませんよね?

Java、C、または C++ を使用している場合は、このマッピングを行う既製のクラスを使用できます。Java では、標準の Collat​​or クラスを使用するか、icu4j Collat​​or クラスを使用します。C/C++ を使用している場合は、C/C++ バージョンの ICU Collat​​or 関数/クラスを使用してください。他の言語の場合、すでにそれを行うライブラリが見つからない限り、運が悪いです。

Java と ICU の両方がタイ語のロケールをサポートし、タイ語で適切な並べ替えを実行できることを私は知っています。すべての文字列が UTF-8 で適切にエンコードされていることを確認してください。

それらを見つけるのに役立ついくつかのリンクを次に示します。

標準 Java ライブラリ Collat​​or: http://docs.oracle.com/javase/7/docs/api/java/text/Collat​​or.html#getCollat​​ionKey(java.lang.String)

C++ コレーター クラス: http://icu-project.org/apiref/icu4c/classicu_1_1Collat ​​or.html#ae0bc68d37c4a88d1cb731adaa5a85e95

また、ロケールごとに大文字と小文字を区別せずに並べ替えることができる別の並べ替えキーを作成することもできます (はい、大文字と小文字のマッピングはロケールを区別します!)、アクセントを区別せず、Unicode バリアントを区別しない、または上記の任意の組み合わせを使用できます。唯一の問題は、ソート可能な各プロパティに対応する多くのプロパティがあり、基本の「名前」プロパティを更新するときにそれらすべてを同期させなければならないことです。知っていることは面倒ですが、それでも、アプリやビジネス ロジック レイヤーで並べ替えを行うよりはましです。

範囲を持つカーソルにも注意してください。たとえば、英語では、文字のアクセントを無視します。したがって、「Ö」は「O」と同じ方法でソートされ、「M」から「Z」の範囲に表示されます。ただし、スウェーデン語では、アクセント付きの文字は "Z" の後に並べ替えられます。したがって、「M」から「Z」までの範囲を指定すると、「Ö」で始まる一連のレコードが含まれます。これらのレコードは、英語では存在するはずですが、スウェーデン語では存在しないはずです。

これは、ドキュメントのテキスト プロパティで分割する場合、シャーディングにも影響します。どの範囲がどのシャードに入るのかに注意してください。ハッシュのように、ロケールに依存しないものを分割する方がよいでしょう。

于 2014-06-04T06:08:27.037 に答える