SQL では、SQL LIKE を使用して電子メール アドレスをかなりうまく検索できます。
「stack@domain.com」という電子メールで、「stack」、「@domain.com」、「domain.com」、または「domain」を検索すると、目的の電子メール アドレスが返されます。
ElasticSearch で同じ結果を得るにはどうすればよいですか?
nGram、edgeNGram、uax_url_email などで遊んでみましたが、検索結果はかなり悪いものでした。間違っている場合は修正してください。次のことを行う必要があるようです。
- index_analyzer 用
- 「キーワード」、「空白」、または「uax_url_email」トークナイザーを使用して、メールがトークン化されないようにする
- しかし、ワイルドカードクエリは機能しないようです(少なくともタイヤでは)
- フィルターには「nGram」または「edgeNGram」を使用します
- 「first-second」を検索すると「first@domain.com」が表示されるなど、常に不要な結果が多すぎます。
- 「キーワード」、「空白」、または「uax_url_email」トークナイザーを使用して、メールがトークン化されないようにする
- search_analyzer 用
- nGramをしないでください
1 つの実験コード
tire.settings :number_of_shards => 1,
:number_of_replicas => 1,
:analysis => {
:filter => {
:db_ngram => {
"type" => "nGram",
"max_gram" => 255,
"min_gram" => 3 }
},
:analyzer => {
:string_analyzer => {
"tokenizer" => "standard",
"filter" => ["standard", "lowercase", "asciifolding", "db_ngram"],
"type" => "custom" },
:index_name_analyzer => {
"tokenizer" => "standard",
"filter" => ["standard", "lowercase", "asciifolding"],
"type" => "custom" },
:search_name_analyzer => {
"tokenizer" => "whitespace",
"filter" => ["lowercase", "db_ngram"],
"type" => "custom" },
:index_email_analyzer => {
"tokenizer" => "whitespace",
"filter" => ["lowercase"],
"type" => "custom" }
}
} do
mapping do
indexes :id, :index => :not_analyzed
indexes :name, :index_analyzer => 'index_name_analyzer', :search_analyzer => 'search_name_analyzer'
indexes :email, :index_analyzer => 'index_email_analyzer', :search_analyzer => 'search_email_analyzer'
end
end
うまく機能しない特定のケース:
- ハイフン付きのメール (email-hyphen@domain.com など)
- 先頭または末尾のクエリ文字列 '@'
- 完全一致
- 「 @ 」などのワイルドカードを使用して検索すると、非常に予期しない結果が得られます。
「aaa@email.com」、「aaa_0@email.com」、「aaa-0@email.com」があるとします。「aaa」を検索すると、「aaa@a.com」「aaa-0@email.コム。「aaa*」で検索するとすべて表示されますが、「aaa-*」では何も表示されません。では、完全一致のワイルドカードクエリを実行するにはどうすればよいでしょうか。これらのタイプのクエリでは、さまざまなトークナイザー/アナライザーでほぼ同じ結果が得られます。
マッピングを変更するたびにこれらを行います: Model.tire.index.delete Model.tire.create_elasticsearch_index Model.tire.index.import Model.all
参考文献: