2017-01-17 12 views
0

У меня есть JsonObjects, которые я ищу в Elasticsearch из приложения Java, используя Java API для построения searchQueries. Объекты содержат поле под названием «такое», которое содержит searchString, с которым должен быть найден JsonObject, например простой поисковой строкой будет «STVBBM160A». Кроме обычных символов aZ 0-9 searchString также может выглядеть следующим образом: «STV-157ABR», «FG/42-W3» или «DDM000.074.6652»Как создать Elasticsearch-Query с функциями startWith и специальными символами

Поиск должен возвращать результаты уже тогда, когда только первые символы помещаются в поле поиска, которое оно выполняет для поиска типа «FG/42»

Моя проблема: поиск иногда не возвращает результатов вообще, но когда последний символ вводится, он находит правильное документ.

Что я пытался: сначала я хотел использовать WildcardQuery, где запрос был бы «typedStuff *», но WildcardQuery не возвращал никаких результатов вообще, как только я набирал что-либо, кроме * (Он работал для других searchFields с другими значениями)

Теперь я использую QueryStringQuery, который также принимает ввод и помещает символ * в конец. Убегая QueryString, я могу искать строки, такие как «F-G/42» и т. Д., Но поиск «DDM000.074.6652» не возвращает никаких результатов, пока elasticsearch не проведет всю строку для поиска. Кроме того, когда я набираю «STV», все результаты с «STV-xxxxx» (содержащие «-» после STV) возвращаются, но не объект с «STVBBM160A», снова до тех пор, пока вся строка не будет указана для поиска (без отображения любые результаты Inbetween как только SearchString является «STVB»)

Это запрос, я использую прямо сейчас:

{ 
    "size": 1000, 
    "min_score": 1, 
    "query": { 
    "bool": { 
     "must": [ 
     { 
      "query_string": { 
      "query": "MY_DATA_TYPE", 
      "fields": [ 
       "doc.db_doc_type" 
      ] 
      } 
     }, 
     { 
      "query_string": { 
      "query": "MY_SPECIFIC_TYPE", 
      "fields": [ 
       "doc.db_doc_specific" 
      ] 
      } 
     } 
     ], 
     "should": { 
     "query_string": { 
      "query": "STV*", 
      "fields": [ 
      "doc.such" 
      ], 
      "boost": 3, 
      "escape": true 
     } 
     } 
    } 
    } 
} 

Это старый запрос с WildCardQuery, который не возвращает результаты отсутствуют, если нет запросаString, но *:

{ 
    "size": 50, 
    "min_score": 1, 
    "query": { 
    "bool": { 
     "must": [ 
     { 
      "query_string": { 
      "query": "MY_DATA_TYPE", 
      "fields": [ 
       "doc.db_doc_type" 
      ] 
      } 
     }, 
     { 
      "query_string": { 
      "query": "MY_SPECIFIC_TYPE", 
      "fields": [ 
       "doc.db_doc_specific" 
      ] 
      } 
     } 
     ], 
     "should": { 
     "wildcard": { 
      "doc.such": { 
      "wildcard": "STV*", 
      "boost": 3 
      } 
     } 
     } 
    } 
    } 
} 

При использовании PrefixQuery, поиск также не возвращает никаких результатов вообще (с и без *):

{ 
    "size": 50, 
    "min_score": 1, 
    "query": { 
    "bool": { 
     "must": [ 
     { 
      "query_string": { 
      "query": "MY_DATA_TYPE", 
      "fields": [ 
       "doc.db_doc_type" 
      ] 
      } 
     }, 
     { 
      "query_string": { 
      "query": "MY_SPECIFIC_TYPE", 
      "fields": [ 
       "doc.db_doc_specific" 
      ] 
      } 
     } 
     ], 
     "should": { 
     "prefix": { 
      "doc.such": { 
      "prefix": "HSTKV*", 
      "boost": 3 
      } 
     } 
     } 
    } 
    } 
} 

Как этот запрос может быть изменен для достижения цели получения всех результатов, начиная с указанной строкой, независимо от того, если Поле doc.such также содержит числа или специальные символы, такие как «_» или «.». или "/" ?

Заранее спасибо

+2

Этот ответ должен помочь: http://stackoverflow.com/questions/30666371/how-to-wisely-combine-shingles-and -edgengram-to-обеспечить-flexible-full-text-searc (подсказка: вам нужно использовать токенизатор edgeNGram вместо использования префикса и подстановочных запросов) – Val

+0

Хорошо, поэтому мне нужно будет установить анализатор для поля «такой ». Будем искать «How-to» ;-) Спасибо за ваш комментарий – user2122552

+0

Время, позволяющее, я дам ответ на этот вопрос ;-) – Val

ответ

1

Как только вы хотите запросить префиксы, суффиксы или подстроку в серьезном образе, вы должны использовать nGrams. В вашем случае, поскольку вы только после префиксов, edgeNGram tokenizer будет в порядке. Вы должны изменить настройки вашего индекса, чтобы быть как этот:

PUT your_index 
{ 
    "settings": { 
    "analysis": { 
     "analyzer": { 
     "prefix_analyzer": { 
      "tokenizer": "prefix_tokenizer", 
      "filter": [ 
      "lowercase" 
      ] 
     }, 
     "search_prefix_analyzer": { 
      "tokenizer": "keyword", 
      "filter": [ 
      "lowercase" 
      ] 
     } 
     }, 
     "tokenizer": { 
     "prefix_tokenizer": { 
      "type": "edgeNGram", 
      "min_gram": "1", 
      "max_gram": "25" 
     } 
     } 
    } 
    }, 
    "mappings": { 
    "your_type": { 
     "properties": { 
     "doc": { 
      "properties": { 
      "such": { 
       "type": "string", 
       "fields": { 
       "starts_with": { 
        "type": "string", 
        "analyzer": "prefix_analyzer", 
        "search_analyzer": "search_prefix_analyzer" 
       } 
       } 
      } 
      } 
     } 
     } 
    } 
    } 
} 

Что будет с этим анализатором является то, что при индексировании F-G/42-W3 следующие маркеры будут индексироваться: f, f-, f-g, f-g/, f-g/4, f-g/42, f-g/42-, f-g/42-w, f-g/42-w3.

Во время поиска мы просто вводим строчный ввод пользователя, а префикс будет сопоставляться с индексированными токенами.

Тогда ваш запрос просто может быть преобразован в match запроса:

{ 
    "size": 1000, 
    "min_score": 1, 
    "query": { 
    "bool": { 
     "must": [ 
     { 
      "query_string": { 
      "query": "MY_DATA_TYPE", 
      "fields": [ 
       "doc.db_doc_type" 
      ] 
      } 
     }, 
     { 
      "query_string": { 
      "query": "MY_SPECIFIC_TYPE", 
      "fields": [ 
       "doc.db_doc_specific" 
      ] 
      } 
     } 
     ], 
     "should": { 
     "match": { 
      "doc.such": { 
      "query": "F-G/4" 
      } 
     } 
     } 
    } 
    } 
} 
+0

Любое повезло с этим? – Val

+0

Привет Вал, ваше решение действительно работает, но я решил немного упростить подход, используя ключевое слово-токенизатор для индексирования и поиска вместе с префиксомPhraseMatchQuery. Таким образом, существуют разные подходы. В текущем нужно создать меньший индекс, чем nGram-Filters. Спасибо за помощь! – user2122552

+0

Хорошо, что бы ни работало для вас, просто знайте, что префиксPhraseMatchQuery будет масштабироваться менее эффективно, чем ngram-подход по мере роста ваших данных. – Val