Elasticsearch:在字符串中搜索单词并获得分数的最佳方法是什么?

时间:2016-02-23 16:17:59

标签: php elasticsearch

我正在使用ElasticSearch的PHP客户端,每当我想搜索字符串中“隐藏”的单词时,我发现很难返回得分的结果。

这是一个例子:

我想获取字段“file”中包含“anses”字样的所有文档,文件命名如下: axx14anses19122015.zip

我对此了解

我知道我应该对这些词语进行标记,不能意识到该怎么做。 我也读过关于聚合的内容,但我是ES的新手,我必须尽快交付工作。

到目前为止我尝试了什么

  • REGEXP:使用正则表达式非常昂贵,并且不会返回任何分数,这是为了缩小结果并为用户提供准确信息所必需的。

  • 通配符:同样的事情,缓慢而没有分数

  • 自己的脚本我有一个字典并使用regexp搜索关键词,如果匹配,则在该匹配文档中使用该词创建一个新字段。原因是创建一个TOKEN所以在将来的搜索中我可以使用常规匹配分数。否定的一面:我的老板完全拒绝了字典,所以我在这里要求任何想法。

提前致谢。

2 个答案:

答案 0 :(得分:5)

我建议您nGram tokenizer查看示例 我将创建一个分析器和一个doc类型的映射

PUT /test_index
{
   "settings": {
      "number_of_shards": 1,
      "analysis": {
         "tokenizer": {
            "ngram_tokenizer": {
               "type": "nGram",
               "min_gram": 4,
               "max_gram": 4,
               "token_chars": [ "letter", "digit" ]
            }
         },
         "analyzer": {
            "ngram_tokenizer_analyzer": {
               "type": "custom",
               "tokenizer": "ngram_tokenizer",
               "filter": [
                  "lowercase"
               ]
            }
         }
      }
   },
   "mappings": {
      "doc": {
         "properties": {
            "text_field": {
               "type": "string",
               "term_vector": "yes",
               "analyzer": "ngram_tokenizer_analyzer"
            }
         }
      }
   }
}

之后,我将使用您的文件名

插入文档
PUT /test_index/doc/1
{
    "text_field": "axx14anses19122015"
}

现在我将使用查询匹配

POST /test_index/_search
{
    "query": {
        "match": {
           "text_field": "anses"
        }
    }
}

并会收到像这样的回复

{
   "took": 8,
   "timed_out": false,
   "_shards": {
      "total": 1,
      "successful": 1,
      "failed": 0
   },
   "hits": {
      "total": 1,
      "max_score": 0.10848885,
      "hits": [
         {
            "_index": "test_index",
            "_type": "doc",
            "_id": "1",
            "_score": 0.10848885,
            "_source": {
               "text_field": "axx14anses19122015"
            }
         }
      ]
   }
}

我做了什么? 我刚刚创建了一个nGram标记器,它将以4个字符的形式爆炸我们的字符串,并将这些术语分开索引,当我搜索字符串的一部分时将搜索它们。 要了解详情,请阅读这篇文章https://qbox.io/blog/an-introduction-to-ngrams-in-elasticsearch 希望它有所帮助!

答案 1 :(得分:0)

在尝试之后好了 - 很多次它起作用了。我会分享解决方案以防万一其他人需要它。非常感谢Waldemar,这是一个非常好的方法,我仍然不明白它为什么不起作用。

curl -XPUT 'http://ipaddresshere/tokentest' -d 
'{ "settings": 
    { "number_of_shards": 1, "analysis" : 
          { "analyzer" : { "myngram" : { "tokenizer" : "mytokenizer" } },
            "tokenizer" : { "mytokenizer" : { 
                           "type" : "nGram", 
                           "min_gram" : "3", 
                           "max_gram" : "5", 
                           "token_chars" : [ "letter", "digit" ] } } } },  
      "mappings": 
            { "doc" : 
                  { "properties" : 
                         { "field" : { 
                          "type" : "string", 
                          "term_vector" : "yes", 
                          "analyzer" : "myngram" } } } } }'

对于不好的缩进感到抱歉,我真的很着急,但想要发布解决方案。

所以,这将取自" field"然后将它分成nGrams,长度为3到5.例如:" abcanses14f.zip"将导致:

abc,abca,abcan,bca,bcan,bcans等等......直到它达到一个或多个与之相关的分数或类似的术语。