150

最近ElasticSearchを使い始めましたが、単語の一部を検索できないようです。

例:ElasticSearchでインデックス付けされたcouchdbからの3つのドキュメントがあります:

{
  "_id" : "1",
  "name" : "John Doeman",
  "function" : "Janitor"
}
{
  "_id" : "2",
  "name" : "Jane Doewoman",
  "function" : "Teacher"
}
{
  "_id" : "3",
  "name" : "Jimmy Jackal",
  "function" : "Student"
} 

だから今、私は「Doe」を含むすべてのドキュメントを検索したいと思います

curl http://localhost:9200/my_idx/my_type/_search?q=Doe

それはヒットを返しません。しかし、私が検索すると

curl http://localhost:9200/my_idx/my_type/_search?q=Doeman

1つのドキュメント(John Doeman)を返します。

インデックスのプロパティとして、さまざまなアナライザーとさまざまなフィルターを設定してみました。また、本格的なクエリを使用してみました(例:

{
  "query": {
    "term": {
      "name": "Doe"
    }
  }
}

)しかし、何も機能していないようです。

「Doe」を検索するときに、ElasticSearchでJohnDoemanとJaneDoewomanの両方を検索するにはどうすればよいですか?

アップデート

Igorが提案したように、次のようにnGramトークナイザーとフィルターを使用しようとしました。

{
  "index": {
    "index": "my_idx",
    "type": "my_type",
    "bulk_size": "100",
    "bulk_timeout": "10ms",
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "type": "custom",
          "tokenizer": "my_ngram_tokenizer",
          "filter": [
            "my_ngram_filter"
          ]
        }
      },
      "filter": {
        "my_ngram_filter": {
          "type": "nGram",
          "min_gram": 1,
          "max_gram": 1
        }
      },
      "tokenizer": {
        "my_ngram_tokenizer": {
          "type": "nGram",
          "min_gram": 1,
          "max_gram": 1
        }
      }
    }
  }
}

私が今抱えている問題は、すべてのクエリがすべてのドキュメントを返すことです。ポインタはありますか?nGramの使用に関するElasticSearchのドキュメントは素晴らしいものではありません...

4

11 に答える 11

90

私もnGramを使っています。標準のトークナイザーと nGram をフィルターとして使用します。これが私のセットアップです:

{
  "index": {
    "index": "my_idx",
    "type": "my_type",
    "analysis": {
      "index_analyzer": {
        "my_index_analyzer": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "mynGram"
          ]
        }
      },
      "search_analyzer": {
        "my_search_analyzer": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "standard",
            "lowercase",
            "mynGram"
          ]
        }
      },
      "filter": {
        "mynGram": {
          "type": "nGram",
          "min_gram": 2,
          "max_gram": 50
        }
      }
    }
  }
}

50文字までの単語パーツを見つけてみましょう。必要に応じて max_gram を調整します。ドイツ語の単語は非常に大きくなる可能性があるため、高い値に設定しました。

于 2011-09-20T09:47:54.130 に答える
68

先頭および末尾のワイルドカードを使用した検索は、大規模なインデックスでは非常に遅くなります。単語のプレフィックスで検索できるようにする場合は、先頭のワイルドカードを削除します。単語の途中で部分文字列を見つける必要がある場合は、ngram トークナイザーを使用することをお勧めします。

于 2011-06-24T17:23:40.970 に答える
68

マッピングを変更する必要はないと思います。query_stringを使用してみてください。完璧です。すべてのシナリオは、デフォルトの標準アナライザーで機能します。

データがあります:

{"_id" : "1","name" : "John Doeman","function" : "Janitor"}
{"_id" : "2","name" : "Jane Doewoman","function" : "Teacher"}

シナリオ 1:

{"query": {
    "query_string" : {"default_field" : "name", "query" : "*Doe*"}
} }

応答:

{"_id" : "1","name" : "John Doeman","function" : "Janitor"}
{"_id" : "2","name" : "Jane Doewoman","function" : "Teacher"}

シナリオ 2:

{"query": {
    "query_string" : {"default_field" : "name", "query" : "*Jan*"}
} }

応答:

{"_id" : "1","name" : "John Doeman","function" : "Janitor"}

シナリオ 3:

{"query": {
    "query_string" : {"default_field" : "name", "query" : "*oh* *oe*"}
} }

応答:

{"_id" : "1","name" : "John Doeman","function" : "Janitor"}
{"_id" : "2","name" : "Jane Doewoman","function" : "Teacher"}

編集 - 春のデータ弾性検索と同じ実装 https://stackoverflow.com/a/43579948/2357869

query_string が他のものより優れているもう 1 つの説明 https://stackoverflow.com/a/43321606/2357869

于 2017-04-07T13:00:01.293 に答える
7

ここで説明されているソリューションを試してください: ElasticSearch での正確な部分文字列検索

{
    "mappings": {
        "my_type": {
            "index_analyzer":"index_ngram",
            "search_analyzer":"search_ngram"
        }
    },
    "settings": {
        "analysis": {
            "filter": {
                "ngram_filter": {
                    "type": "ngram",
                    "min_gram": 3,
                    "max_gram": 8
                }
            },
            "analyzer": {
                "index_ngram": {
                    "type": "custom",
                    "tokenizer": "keyword",
                    "filter": [ "ngram_filter", "lowercase" ]
                },
                "search_ngram": {
                    "type": "custom",
                    "tokenizer": "keyword",
                    "filter": "lowercase"
                }
            }
        }
    }
}

ディスク使用量の問題と長すぎる検索用語の問題を解決するために、短い 8 文字のngramが使用されます (構成: "max_gram": 8 )。8 文字を超える用語を検索するには、検索をブール AND クエリに変換して、その文字列内の個別の 8 文字の部分文字列をすべて検索します。たとえば、ユーザーが大きなヤード(10 文字の文字列) を検索した場合、検索は次のようになります。

「arge ya AND arge yar AND rge yard .

于 2015-05-06T13:09:00.490 に答える
-6

どうでも。

Lucene のドキュメントを確認する必要がありました。ワイルドカードが使えるようです!:-)

curl http://localhost:9200/my_idx/my_type/_search?q=*Doe*

トリックを行います!

于 2011-06-24T11:56:20.523 に答える