2016-09-30 1 views
0

Я ищу лучший способ.Ищите более сжатый способ совпадения с префиксами на нескольких терминах

У меня есть произвольное количество входных условий (допустим, это фамилии) от пользователя. Я хочу выполнить префиксный поиск по каждому из них и увеличить оценку для любых совпадений.

Непроанализированный prefix query - это то, что я использую сейчас - см. Пример ниже - однако я также беру на себя ответственность за то, что анализатор в противном случае сделал бы, создав пользовательское программирование, чтобы разделить входные условия на пробелов, обрезки, обрезать их, а затем построить ряд префиксных запросов с помощью токенов, чтобы таким образом повысить скоринг.

  1. Пример ввода - это куча имен, таких как «Смит, Родригес, РОБЕРТС, ДО».
  2. Потом программирование разбирает их на лексемы и нижний регистр их:
    кузнец
    Родригез
    Roberts
    лань

  3. Наконец я построить несколько запросов префиксы, чтобы увеличить разрыв в счете, как так

"should": [ 
    { 
     "dis_max" : { 
      "tie_breaker": 1, 
      "boost": 3, 
      "queries": [ 
       { 
        "prefix" : { "surname": "doe"} 
       }, 
       { 
        "prefix" : { "surname": "rob"} 
       }, 
       { 
        "prefix" : { "surname": "rod"} 
       }, 
       { 
        "prefix" : { "surname": "smi"} 
       } 
      ] 
     } 
    } 
], 

Я не могу не думать, что я делаю это неэффективно, и что elasticsearch может предоставить более умные функции, о которых я не знаю. Я хочу проанализировать форму префиксного запроса, чтобы сделать мою жизнь легкой. Например, было бы идеально пройти ввод дословно для анализа до такого упругого запроса "someAnalyzedPrefix": {"surname": "smith rodriguez roberts doe", prefix_length: 3} Я немного сплю здесь, но вы получаете суть того, что я ищу более резкое решение.

Интересно, может ли любой другой вид запросов влиять на один и тот же результат, принимая на себя ответственность за анализ.

Предложения по улучшению приветствуются, иначе я буду придерживаться шаблона выше, поскольку он удовлетворяет потребность, хотя и не обязательно красиво.

ответ

0

Я думаю, что Edge NGram tokenizer/filter поможет.

Вы можете иметь индекс только с индексом и анализаторы search only. Анализатор индекса будет содержать строчные буквы и делать красные ngrams. У анализаторов поиска есть Word Delimiter filter, которые позаботятся о разборе вашего запроса. Обратите внимание, что вы можете опустить фильтр Word Delimiter и просто использовать Standard tokenizer вместо Whitespace, и он позаботится о его разбиении на пробелы и запятые. Разделитель слов дает вам больше контроля над тем, как вы хотите разделить токены.

Вы всегда можете использовать _analyze api, чтобы проверить, как ваша токенизация будет работать.

Индекс Настройки:

{ 
    "settings" : { 
     "analysis" : { 
      "filter": { 
      "word_delimiter_filter": { 
        "preserve_original": "true", 
        "catenate_words": "true", 
        "catenate_all": "true", 
        "split_on_case_change": "true", 
        "type": "word_delimiter", 
        "catenate_numbers": "true", 
        "stem_english_possessive": "false" 
      }, 
      "edgengram_filter": { 
        "type":  "edge_ngram", 
        "min_gram": 3, 
        "max_gram": 3 
      } 
     }, 
     "analyzer" : { 
       "my_edge_ngram_analyzer" : { 
        "filter": [ 
         "lowercase", 
         "edgengram_filter" 
        ], 
        "type": "custom", 
        "tokenizer" : "whitespace" 
       }, 
       "my_edge_ngram_search_analyzer": { 
        "filter": [ 
        "lowercase", 
        "word_delimiter_filter", 
        "edgengram_filter" 
        ], 
        "type": "custom", 
        "tokenizer": "whitespace" 
       } 
      } 
     } 
    } 
} 

Mapping:

{ 
     "properties": { 
     "surname_edgengrams": { 
      "type": "string", 
      "analyzer": "my_edge_ngram_analyzer", 
      "search_analyzer": "my_edge_ngram_search_analyzer" 
     }, 
     "surname": { 
      "type": "string", 
      "index": "not_analyzed", 
      "copy_to": [ 
       "surname_edgengrams" 
      ] 
     } 
     } 
} 

Я проиндексированы некоторые документы с использованием насыпной API:

{ "index" : { "_index" : "edge_test", "_type" : "test_mapping", "_id" : "1" } } 
{ "surname" : "Smith" } 
{ "index" : { "_index" : "edge_test", "_type" : "test_mapping", "_id" : "2" } } 
{ "surname" : "Rodriguez" } 
{ "index" : { "_index" : "edge_test", "_type" : "test_mapping", "_id" : "3" } } 
{ "surname" : "Roberts" } 
{ "index" : { "_index" : "edge_test", "_type" : "test_mapping", "_id" : "4" } } 
{ "surname" : "Doe" } 

и использовать следующий шаблон поиска:

{ 
    "query" : { 
     "bool" : { 
      "should" : [{ 
        "match" : { 
         "surname_edgengrams" : { 
          "query" : "Smith, Rodriguez, ROBERTS, doe", 
          "boost" : 3 
         } 
        } 
       } 
      ] 
     } 
    } 
} 

Результаты:

{ 
    "took": 5, 
    "timed_out": false, 
    "_shards": { 
    "total": 3, 
    "successful": 3, 
    "failed": 0 
    }, 
    "hits": { 
    "total": 4, 
    "max_score": 0.14085768, 
    "hits": [ 
     { 
     "_index": "edge_test", 
     "_type": "test_mapping", 
     "_id": "1", 
     "_score": 0.14085768, 
     "_source": { 
      "surname": "Smith" 
     } 
     }, 
     { 
     "_index": "edge_test", 
     "_type": "test_mapping", 
     "_id": "3", 
     "_score": 0.14085768, 
     "_source": { 
      "surname": "Roberts" 
     } 
     }, 
     { 
     "_index": "edge_test", 
     "_type": "test_mapping", 
     "_id": "2", 
     "_score": 0.13145615, 
     "_source": { 
      "surname": "Rodriguez" 
     } 
     }, 
     { 
     "_index": "edge_test", 
     "_type": "test_mapping", 
     "_id": "4", 
     "_score": 0.065728076, 
     "_source": { 
      "surname": "Doe" 
     } 
     } 
    ] 
    } 
} 

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

  • Нет связанных вопросов^_^