Mongodbで地理空間インデックスを使用した全文検索の使用

サイモン

あなたがいる場所に最も近いホテルをユーザーが検索できるAndroidアプリを開発したいとします。これは、たとえばAirBnbなど、最近のアプリでは非常に一般的です。

これは私が使用しているデータセットです:

{
    "name" : "The Most Amazing Hotel",
    "city" : "India",
    "type": "Point"
    "coord": [
        -56.16082,
        61.15392
      ]
}

{
    "name" : "The Most Incredible Hotel",
    "city" : "India",
    "type": "Point"
    "coord": [
        -56.56285,
        61.34590
      ]
}

{
    "name" : "The Fantastic GuestHouse",
    "city" : "India",
    "type": "Point"
    "coord": [
        -56.47085,
        61.11357
      ]
}

ここでフィールドにテキストインデックスを作成して、name名前で検索し、座標に基づいて地理空間インデックスで並べ替えるようにします。

したがって、「The Most」という単語を検索すると、名前で「The Most」という単語が検索され、「The Mostinthemost」という単語が含まれる最寄りのホテルが返されます。

mongodbはこのタイプの検索もサポートしていますか?

ここでmongodbのガイダンスを読んでいます:https://docs.mongodb.org/manual/core/index-text/

複合テキストインデックスには、マルチキーや地理空間インデックスフィールドなどの他の特別なインデックスタイプを含めることはできません。

私が理解している限り、私は複合テキストインデックスを作成していません。これは単純なテキストインデックスですnameつまり、cityANDnameフィールドではなくフィールドのテキストのみにインデックスを付けています

ブレイクス7

このような操作のユースケースを正当化するのは非常に難しいため、これをまったく必要としないという公正なケースがあります。「ホテルの検索」は、「テキスト」の組み合わせではないことを主張します。 「」と「geoSpatial」検索が実際に適用されます。

実際には、「ほとんどの人」、主要な基準の一部として、ある場所に近い、または訪問したいさまざまな場所に近いものを探している可能性が高く、他の「勝者」は「コスト」に重きを置いている可能性があります。 "、"評価 "、"ブランド "、"施設 "、そしておそらく飲食店などへの近さ

そのリストに「テキスト検索」追加することは非常に異なることであり、この特定のアプリケーションではあまり実用的ではない可能性があります。

それでも、これはおそらく説明に値するものであり、少なくともこのユースケースでは2つの概念が実際には「メッシュ」にならない理由について、ここで理解すべきいくつかの概念があります

スキーマの修正

まず、データスキーマを少し「微調整」することを提案したいと思います。

{
    "name" : "The Most Amazing Hotel",
    "city" : "India",
    "location": {
        "type": "Point",
        "coordinates": [
               72.867804,
               19.076033
        ]
    }
}

これは少なくとも"location"インデックス作成用の有効なGeoJSONオブジェクトとして提供され、一般にクエリとストレージのオプションが増えるため、従来の座標ペアではなくGeoJSONが必要です。さらに、距離は同等ではなくメートルに標準化されます。世界中のラジアン」。

彼らが一緒に働かない理由

したがって、一度に複数の特別なインデックスを使用することはできないという点で、基本的に正しい読み方です。最初に複合インデックスの定義を見てください。

db.hotels.createIndex({ "name": "text", "location": "2dsphere" })

{"ok":0、 "errmsg": "不正なインデックスキーパターン{名前:\" text \ "、場所:\" 2dsphere \ "}:1つのインデックスに複数のインデックスプラグインを使用することはできません。"、 「コード」:67}

だからそれはできません。個別に検討しても:

db.hotels.createIndex({ "name": "text" })
db.hotels.createIndex({ "location": "2dsphere" })

次に、クエリを実行してみてください。

db.hotels.find({
    "location": {
        "$nearSphere": {
            "$geometry": {
                "type": "Point",
                "coordinates": [
                   72.867804,
                   19.076033
                ]
            }
        }
    },
    "$text": { "$search": "Amazing" }
})

エラー:コマンドが失敗しました:{"waitedMS":NumberLong(0)、 "ok":0、 "errmsg": "テキストとgeoNearは同じクエリでは許可されていません"、 "コード":2}:未定義

これは、これが複合インデックスで3つの方法で定義できなかった理由を実際に裏付けています。

  1. 初期エラーが示すように、MongoDBでこれらの「特別な」インデックスを処理する方法では、基本的に、選択したインデックスタイプの「特別な」ハンドラーに「分岐」する必要があり、2つのハンドラーは同じ場所にありません。

  2. 個別のインデックスを使用する場合でも、ロジックは基本的に「and」条件であるため、MongoDBはとにかく複数のインデックスを実際に選択することはできません。また、両方のクエリ句で「特別な」処理が必要になるため、実際にはそうする必要があります。そして、それはできません。

  3. これが論理的な$or条件であったとしても、基本的にポイント1に戻ります。ここでは、「インデックスの交差」を適用しても、クエリ操作の「トップレベル」で順番に適用する必要ある「特別な」インデックスの別のプロパティがあります。インデックスを選択できるようにします。これらをラップする$orということは、MongoDBがそれを実行できないため、許可されないことを意味します。

しかし、あなたは「チート」することができます

したがって、基本的にそれぞれが排他的である必要があり、それらを一緒に使用することはできません。しかしもちろん、検索のどの順序があなたにとってより重要であるかに応じて、あなたはいつでも「ごまかす」ことができます。

最初に「場所」で:

db.hotels.aggregate([
    { "$geoNear": {
        "near": {
            "type": "Point",
            "coordinates": [
               72.867804,
               19.076033
            ]
        },
        "spherical": true,
        "maxDistance": 5000,
        "distanceField": "distance",
        "query": {
           "name": /Amazing/
        }
    }}
])

あるいは:

db.hotels.find({
    "location": {
        "$nearSphere": {
            "$geometry": {
                "type": "Point",
                "coordinates": [
                   72.867804,
                   19.076033
                ]
            },
            "$maxDistance": 5000
        }
    },
    "name": /Amazing/
})

または最初にテキスト検索で:

db.hotels.find({
    "$text": { "$search": "Amazing" },
    "location": {
        "$geoWithin": {
            "$centerSphere": [[
               72.867804,
               19.076033
            ], 5000 ]
        }
    }
})

これで、各アプローチの選択オプション.explain()を詳しく見て、何が起こっているかを確認できますが、基本的なケースは、それぞれが使用する特別なインデックスを1つだけ選択することです。

最初のケースでは、プライマリに使用されるのはコレクションのgeoSpatialインデックスであり、最初に指定された場所への近接度に基づいて結果を検索し、次にnameフィールドに指定された正規表現引数でフィルタリングします。

2番目のケースでは、「text」インデックスを使用して一次選択を行い(したがって、最初に「Amazing」のものを見つけます)、それらの結果から、geoSpatialフィルター(インデックスを使用しない)を適用します。$geoWithinこの場合、基本的には、指定された距離内のポイントの周りの円$near内を検索してそこで結果をフィルタリングすることにより、aが実行していることと同等です

「すべての」クエリが等しいわけではありません

ただし、考慮すべき重要な点は、アプローチごとに異なる結果が返される可能性が非常に高いということです。最初に場所を絞り込むことにより、検査できるデータは指定された距離内の場所のみであるため、距離外で「驚くべき」ものは追加のフィルターによって考慮されません。

2番目のケースでは、テキスト用語が一次検索であるため、「Amazing」のすべての結果が考慮され、二次フィルターによって返されるアイテムは、最初のテキストから返されることが許可されたアイテムのみです。フィルタ。

2つのクエリ操作(「text」と「geoSpatial」の両方)は非常に異なることを達成しようとするため、これは全体的な考慮事項において非常に重要です。「テキスト」の場合、指定された用語の「上位の結果」を探し、その用語に一致する限られた数の結果のみをランク付けされた順序で返します。これは、他のフィルター条件を適用する場合、その最初の条件を満たしたアイテムの多くが追加の基準を満たさない可能性が高いことを意味します。

要するに、「「驚くべき」すべてのものが必ずしもクエリされたポイントの近くにあるわけではありません」。つまり、ような現実的な制限が100 resultsあり、最もよく一致するのは、これらの100に「近い」アイテムもすべて含まれていない可能性が高いということです。

また、$textオペレーターは実際には、それ自体で結果を実際に「ソート」することはありません。実際の主な目的は、フレーズを「一致」させるだけでなく、結果「スコアリング」して「最良の」一致を一番上に浮かび上がらせることです。これは通常、クエリ自体の「後に」実行され、前述のように、予測値は「ソート」され、ほとんどの場合「制限」されます。集約パイプラインでそれを実行してから2番目のフィルターを適用することは可能ですが、前述のように、これは他の目的で「近い」ものを除外する可能性があります。

逆もまた真である可能性があります(「ポイントから遠く離れたところに多くの「驚くべき」ものがあります」)が、現実的な距離制限があると、これは起こりにくくなります。しかし、与えられた他の考慮事項は、これは真のテキスト検索ではなく、与えられた用語に一致する正規表現を使用することです。

最後に、私は常に"Amazing"ここでの例のフレーズとして使用して"Most"おり、質問で提案されているものではありませんこれは、「and」、「or」、「the」、さらには「in」のように、特定の用語が無視されるという点で、ここのテキストインデックス(およびほとんどの専用テキスト検索製品)で「ステミング」がどのように機能するかによるものです。テキスト検索が行うことであるフレーズにとって実際には価値があるとは見なされないので、同様になります。

したがって、実際に正規表現が必要な場合でも、実際にはそのような用語のマッチングに優れているということは事実です。

結論

これは、「テキスト」クエリが実際にはここに属していないという点で、元のポイントに完全に戻ります。他の便利なフィルターは、通常、真の「geoSpatial」検索基準と連携して機能し、真の「テキスト検索」は重要なもののリストに含まれていません。

より可能性が高いのは、訪問したい目的地からの距離の*「交差点の設定」内、または少なくとも一部またはほとんどに十分近い場所を望んでいることです。そしてもちろん、前述のような他の要素(*「価格」、「サービス」など)は、人々が一般的に考慮したいものです。

この方法で結果を探すのは、実際には「適切」ではありません本当に必要だと思う場合は、「チート」アプローチの1つを適用するか、実際には異なるクエリを使用してから、他のロジックを使用して結果の各セットをマージします。しかし、サーバーがこれを単独で行うことは実際には意味がありません。そのため、サーバーは試行しません。

したがって、最初に地理空間の一致を正しく取得することに焦点を当て、次に結果に重要な他の基準を適用します。しかし、私は「テキスト検索」がとにかくそれらの1つであることが本当に有効であるとは本当に信じていません。代わりに「チート」しますが、本当に必要な場合に限ります。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

インデックスを使用しないMongoDB全文検索

分類Dev

Solr7-地理空間検索を使用した全文検索の実行方法

分類Dev

Luceneを使用したタイムスタンプ付きの地理空間検索

分類Dev

NEST C#を使用したElasticSearchでの複数のインデックスによる全文検索

分類Dev

PostgreSQLでSQLAlchemyを使用して全文検索インデックスを作成する

分類Dev

加重tsvectorを使用したPostgreSQL全文検索に使用するのに最適なインデックス

分類Dev

C#クライアントNestを使用したダイアリックなしのelasticsearchでのインデックス作成と全文検索

分類Dev

Postgres-to_tsvectorで3列以上を使用して全文検索のインデックスを作成します

分類Dev

pymongoで地理空間インデックスを使用する例

分類Dev

MongoDBで地理空間インデックスを作成する

分類Dev

Postgres-PostGisを使用したLINQまたはSQLでの地理空間検索

分類Dev

COPYでデータをインポートした後、インデックスを使用しないPostgreSQL全文検索

分類Dev

半正矢式を使用したMySQL地理空間検索は、同じポイントでnullを返します

分類Dev

EFSを使用した検索インデックスの暗号化

分類Dev

別のマルチキーインデックスを使用した地理空間インデックス...解決策はありますか?

分類Dev

Underscloreを使用したインデックスでのHibernateSearch / Lucene検索

分類Dev

HibernateOgmを使用したMongodbでの全文検索

分類Dev

mongodbのインデックスを使用して値を検索する

分類Dev

APIを使用してcouchbase全文検索インデックスエイリアスを作成する方法

分類Dev

Npgsql:式インデックスを使用して全文検索を正しく実行する

分類Dev

MongoDBで地理空間とタイプインデックスを一緒に作成しますか?

分類Dev

PHPを使用したMongoDB全文検索

分類Dev

HTMLマークアップを使用したリッチテキストでのNeo4jの全文検索

分類Dev

空間インデックスを使用して、互いの範囲内のポイントを検索します

分類Dev

NESTを使用した複数のelasticsearchインデックスの検索

分類Dev

CONTAINSTABLEを使用したSQLServer全文検索クエリでのアンパサンドのエスケープ

分類Dev

Solrを使用したMySQLのインデックス作成と検索

分類Dev

SQLインジェクションを使用した全文検索を使用したADOselectステートメント

分類Dev

空間インデックスを使用したMYSQL

Related 関連記事

  1. 1

    インデックスを使用しないMongoDB全文検索

  2. 2

    Solr7-地理空間検索を使用した全文検索の実行方法

  3. 3

    Luceneを使用したタイムスタンプ付きの地理空間検索

  4. 4

    NEST C#を使用したElasticSearchでの複数のインデックスによる全文検索

  5. 5

    PostgreSQLでSQLAlchemyを使用して全文検索インデックスを作成する

  6. 6

    加重tsvectorを使用したPostgreSQL全文検索に使用するのに最適なインデックス

  7. 7

    C#クライアントNestを使用したダイアリックなしのelasticsearchでのインデックス作成と全文検索

  8. 8

    Postgres-to_tsvectorで3列以上を使用して全文検索のインデックスを作成します

  9. 9

    pymongoで地理空間インデックスを使用する例

  10. 10

    MongoDBで地理空間インデックスを作成する

  11. 11

    Postgres-PostGisを使用したLINQまたはSQLでの地理空間検索

  12. 12

    COPYでデータをインポートした後、インデックスを使用しないPostgreSQL全文検索

  13. 13

    半正矢式を使用したMySQL地理空間検索は、同じポイントでnullを返します

  14. 14

    EFSを使用した検索インデックスの暗号化

  15. 15

    別のマルチキーインデックスを使用した地理空間インデックス...解決策はありますか?

  16. 16

    Underscloreを使用したインデックスでのHibernateSearch / Lucene検索

  17. 17

    HibernateOgmを使用したMongodbでの全文検索

  18. 18

    mongodbのインデックスを使用して値を検索する

  19. 19

    APIを使用してcouchbase全文検索インデックスエイリアスを作成する方法

  20. 20

    Npgsql:式インデックスを使用して全文検索を正しく実行する

  21. 21

    MongoDBで地理空間とタイプインデックスを一緒に作成しますか?

  22. 22

    PHPを使用したMongoDB全文検索

  23. 23

    HTMLマークアップを使用したリッチテキストでのNeo4jの全文検索

  24. 24

    空間インデックスを使用して、互いの範囲内のポイントを検索します

  25. 25

    NESTを使用した複数のelasticsearchインデックスの検索

  26. 26

    CONTAINSTABLEを使用したSQLServer全文検索クエリでのアンパサンドのエスケープ

  27. 27

    Solrを使用したMySQLのインデックス作成と検索

  28. 28

    SQLインジェクションを使用した全文検索を使用したADOselectステートメント

  29. 29

    空間インデックスを使用したMYSQL

ホットタグ

アーカイブ