2016-07-07 2 views
0

Мне нужно найти контакты по электронной почте. Согласно ES documentation, лучший способ достичь этого - использовать токенизатор uax_url_email. Вот мои настройки индекса:ElasticSearch поиск по электронной почте по полному совпадению

settings: { 
    index: { 
    creation_date: "1467895098804", 
    analysis: { 
     analyzer: { 
     email: { 
      type: "custom", 
      tokenizer: "uax_url_email" 
     } 
     } 
    }, 
    number_of_shards: "5", 
    number_of_replicas: "1", 
    uuid: "wL0P6OIaQqqYpFDvIHArTw", 
    version: { 
     created: "2030399" 
    } 
    } 
} 

и отображение:

contact: { 
    dynamic: "false", 
    properties: { 
    contact_status: { 
     type: "string" 
    }, 
    created_at: { 
     type: "date", 
     format: "strict_date_optional_time||epoch_millis" 
    }, 
    email: { 
     type: "string" 
    }, 
    id: { 
     type: "long" 
    }, 
    mailing_ids: { 
     type: "long" 
    }, 
    subscription_status: { 
     type: "string" 
    }, 
    type_ids: { 
     type: "long" 
    }, 
    updated_at: { 
     type: "date", 
     format: "strict_date_optional_time||epoch_millis" 
    }, 
    user_id: { 
     type: "long" 
    } 
    } 
} 

После создания индекса я вставил два документа:

curl -X PUT 'localhost:9200/contacts/contact/1' -d '{"contact_status": "confirmed", "email": "[email protected]", "id": "1", "user_id": "1", "subscription_status": "on"}' 

и

curl -X PUT 'localhost:9200/contacts/contact/2' -d '{"contact_status": "confirmed", "email": "[email protected]", "id": "2", "user_id": "2", "subscription_status": "on"}' 

Тогда я пытаюсь найти контакты по электронной почте по-разному:

curl -X POST 'localhost:9200/contacts/_search?pretty' -d '{"query": {"bool": {"must": [ {"match": {"_all": { "query": "[email protected]", "analyzer": "email" } } } ] } } }' 

я ожидал, чтобы получить 1 результат с идентификатором = 1, но получили пустые хиты:

{ 
    "took" : 1, 
    "timed_out" : false, 
    "_shards" : { 
    "total" : 5, 
    "successful" : 5, 
    "failed" : 0 
    }, 
    "hits" : { 
    "total" : 0, 
    "max_score" : null, 
    "hits" : [ ] 
    } 
} 

Следующий поисковый запрос я тестировал был:

curl -X POST 'localhost:9200/contacts/_search?pretty' -d '{"query": {"bool": {"must": [ {"match": {"_all": { "query": "[email protected]", "analyzer": "email" } } } ] } } }' 

, который вернул 2 результата:

{ 
    "took" : 2, 
    "timed_out" : false, 
    "_shards" : { 
    "total" : 5, 
    "successful" : 5, 
    "failed" : 0 
    }, 
    "hits" : { 
    "total" : 2, 
    "max_score" : 0.016878016, 
    "hits" : [ { 
     "_index" : "contacts", 
     "_type" : "contact", 
     "_id" : "2", 
     "_score" : 0.016878016, 
     "_source" : { 
     "contact_status" : "confirmed", 
     "email" : "[email protected]", 
     "id" : "2", 
     "user_id" : "2", 
     "subscription_status" : "on" 
     } 
    }, { 
     "_index" : "contacts", 
     "_type" : "contact", 
     "_id" : "1", 
     "_score" : 0.016878016, 
     "_source" : { 
     "contact_status" : "confirmed", 
     "email" : "[email protected]", 
     "id" : "1", 
     "user_id" : "1", 
     "subscription_status" : "on" 
     } 
    } ] 
    } 
} 

Но, как вы понимаете, я ожидал получить 1 документ в результатах поиска. Что я делаю не так?

+0

Если 'email' содержит только адрес электронной почты, почему бы вам не сделать это поле' 'index": "not_analyzed" ', а затем использовать фильтр' term' для поиска адреса электронной почты? –

+0

Потому что мне также нужно искать по user_id, id и другим полям. Более того, я хочу выполнить поиск по электронной почте, например: введите 'example' на вкладке и получите список писем, содержащих« пример », в моем случае - оба документа. Или, если я набираю 'gmail.com' => получить документ с идентификатором 1 – Hroft

+0

Я предлагаю такой подход: http://stackoverflow.com/questions/30115867/elasticsearch-analyzer-and-tokenizer-for-emails Если у вас есть какие-либо трудности или другой вариант использования, чем тот, который дал мне знать. –

ответ

1

Это то, что случилось:

«uax_url_email» токенизатор равно «стандартной» Tokenizer (это означает, что вырезает „@“), за исключением, когда он получает образец "<text>@<text>.<text>" в этом случае он не делает . разрезали «@», но принимает всего адрес электронной почты в качестве одного маркеров

Теперь, времени индекс вы определили поле «электронной почты», как «строка», который по умолчанию «стандарт» токенизатор, а это означает - ваш адрес был обозначен как токены: «example» и «gmail.com "! На этапе время поиска вы определили токен-адрес «email», то есть ваш (первый) запрос «[email protected]» не был вообще разблокирован (поскольку он попадает в шаблон электронной почты), поэтому он не соответствует ни одному из примеров "или" gmail.com "(и то же для yahoo). В вашем втором запросе вы искали «example @ google» - это не относится ко всему шаблону электронной почты, так что токенизатор электронной почты работал как «стандартный» токенизатор, что означает, что он сокращает «@» и «токенизировать» пример »и« google «Ищем один в вашем индексе. Так как пример индексируется в ваших двух документах - он подходит для обоих!

Если вы хотите, чтобы иметь возможность сопоставлять только «примерную» часть вашего адреса, вы не можете использовать ваш «электронный» анализатор во время поиска! В любом случае, большую часть времени вы не должны изменять свой анализатор поиска из анализатора индекса!

Помните, что «стандартный» анализатор не будет вырезать «gmail.com» в 2 жетона!

+0

Спасибо за ваше объяснение. Я думал, что задание анализатора в поисковых запросах анализирует свойства, а не поисковый запрос. :(Так как я понимаю, я должен указать анализатор для электронной почты на этапе создания индекса. Проблема в том, что у меня уже есть такая индексная схема для производства с документами 600k +, и единственный способ исправить эту проблему поиска - воссоздать этот индекс? – Hroft

+0

Вы должны указать свой «электронный» анализатор в сопоставлении. Таким образом, каждый новый документ будет анализироваться вместе с ним. Для этого вам нужно только создать новый индекс с новым сопоставлением и переиндексировать свой старый индекс в новый 1. Это очень легко. И снова, вы сможете только соответствовать электронной почте в целом! – israelst

Смежные вопросы