2016-09-30 46 views
0

我正在寻找更好的方法。寻找更简洁的方式来前缀多个条件匹配

我有来自用户的任意数量的输入项(假设他们是姓)。我想在每一个上执行前缀搜索并提高任何比赛的分数。

未分析的prefix query就是我现在使用的内容 - 请参阅下面的示例 - 但是,我还承担了分析程序通过创建自定义编程来分割输入项的功能的责任空格,修剪,下划线,然后用令牌构建一系列前缀查询来提升评分。

  1. 示例输入是像“Smith,Rodriguez,ROBERTS,doe”这样的一群姓氏。
  2. 然后我的编程分析它们为标记,并将其小写为:
    史密斯
    罗德里格斯
    罗伯茨
    母鹿

  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分析器。 索引分析器将只是小写,并使边缘节点。搜索分析器有一个Word Delimiter filter这将负责解析您的查询。 请注意,您可以省略Word分隔符过滤器,只需使用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" 
       } 
      } 
     } 
    } 
} 

映射:

{ 
     "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" 
     } 
     } 
    ] 
    } 
}