2015-06-04 4 views
3

Я пытаюсь создать панель поиска, где наиболее распространенный запрос будет для «serviceOrderNo». "serviceOrderNo" не является номер поле в базе данных, это строка поле. Примеры:Игнорировать ведущие нули с Elasticsearch

000000007 
000000002 
WO0000042 
123456789 
AllTextss 
000000054 
000000065 
000000874 

Наиболее распространенный формат - это просто целое число, исчисленное некоторым количеством нулей.

Как настроить Elasticsearch так, чтобы поиск по «65» соответствовал «000000065»? Я также хочу отдать предпочтение поле «serviceOrderNo» (которое у меня уже есть). Вот где я нахожусь прямо сейчас:

{ 
    "query": { 
     "multi_match": { 
     "query": "65", 
     "fields": ["serviceOrderNo^2", "_all"], 
     } 
    } 
} 

ответ

6

Один из способов сделать это с помощью Lucene вкуса регулярного exression запроса:

https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-regexp-query.html

"query": { 
    "regexp":{ 
     "serviceOrderNo": "[0]*65" 
    } 
} 

Кроме того, запрос Строки запроса также поддерживает небольшой набор специальных символов, более ограниченный набор символов регулярного выражения, AS WELL AS. Люцинные регулярные выражения будут выглядеть так: https://www.elastic.co/guide/en/elasticsearch/reference/1.x/query-dsl-query-string-query.html

"query": { 
    "query_string": { 
     "default_field": "serviceOrderNo", 
     "query": "0*65" 
    } 
} 

Это довольно простые регулярные выражения, как говорят соответствует символ (ы), содержащийся в скобках [0] или символ 0 неограниченное количество раз *.

Если у вас есть возможность повторно проиндексировать или еще не проиндексировать ваши данные, у вас также есть возможность сделать это проще для себя, написав собственный анализатор. Прямо сейчас вы используете анализатор по умолчанию для строк в поле serviceOrderNo. Когда вы индексируете "serviceOrderNo":"00000065", ES интерпретирует это просто как 00000065.

Ваш пользовательский анализатор может подделать это поле как «0000065», так и «65», используя то же регулярное выражение. Преимущество этого заключается в том, что Regex работает только один раз во время индекса, а не каждый раз, когда вы запускаете свой запрос, потому что ES будет искать как «0000065», так и «65».

Вы также можете проверить the ES website documentation on Analyzers.

"settings":{ 
    "analysis": { 
     "filter":{ 
      "trimZero": { 
       "type":"pattern_capture", 
       "patterns":"^0*([0-9]*$)" 
      } 
     }, 
     "analyzer": { 
      "serviceOrderNo":{ 
       "type":"custom", 
       "tokenizer":"standard", 
       "filter":"trimZero" 
      } 
     } 
    } 
}, 
"mappings":{ 
    "serviceorderdto": { 
     "properties":{ 
      "serviceOrderNo":{ 
       "type":"String", 
       "analyzer":"serviceOrderNo" 
      } 
     } 
    } 
} 
+1

Я просто понял, что я сделал действительно ленивую работу написания регулярных выражений для пользовательского анализатора. Я обновил свой ответ трижды проверенным преемником. – IanGabes

+0

Я пробовал ваше решение, и это сработало. Благодаря!Я нахожусь на ранних этапах создания ES, поэтому я могу повторно индексировать, поэтому ваше решение работает хорошо. Я также опубликовал другой ответ, не уверенный, с кем мы еще будем. Если вы найдете какие-либо недостатки решения ngram, отправьте комментарий. –

0

Один из способов сделать это заключается в использовании ngram token filter так, что «12345» получает лексемы как:

[ 1, 2, 3, 4, 5 ] 
[ 12, 23, 34, 45 ] 
[ 123, 234, 345 ] 
[ 12345 ] 

Когда метках таким образом, «65» является матч для «000000065».

Чтобы установить это, создать новый индекс, который имеет собственный анализатор, который использует Ngram фильтр:

POST /my-index 
{ 
    "mappings": { 
     "serviceorderdto": { 
     "properties": { 
      "serviceOrderNo": { 
       "type": "string", 
       "analyzer": "autocomplete" 
      } 
     } 
     } 
    }, 
    "settings": { 
     "analysis": { 
     "filter": { 
      "autocomplete_filter": { 
       "type": "ngram", 
       "min_gram": 1, 
       "max_gram": 20 
      } 
     }, 
     "analyzer": { 
      "autocomplete": { 
       "type": "custom", 
       "tokenizer": "standard", 
       "filter": [ 
        "lowercase", 
        "autocomplete_filter" 
       ] 
      } 
     } 
     } 
    } 
} 

Индекс некоторых данных. Затем запустите запрос:

GET /my-index/_search 
{ 
    "query": { 
     "multi_match": { 
      "query": "55", 
      "fields": [ 
       "serviceOrderNo^2", 
       "_all" 
      ] 
     } 
    } 
} 
Смежные вопросы