在没有预定义模式的情况下使用ngrams而不是通配符

时间:2013-03-12 00:55:46

标签: elasticsearch

我最近发现我不应该使用通配符进行弹性搜索查询。相反,我被告知我应该使用ngrams。在我的实验中,这非常有效。我想做的是能够告诉Elasticsearch对所有映射字段(或适合特定模式的映射属性)使用ngrams。 例如:

CURL -XPUT 'http://localhost:9200/test-ngram-7/' -d '{
     "mappings": {
         "person": {
             "properties": {
                 "name": {
                     "type": "string",
                     "analyzer": "partial"
                 }
             }
         }
     },
     "settings": {
         "analysis": {
             "filter": {
                 "lb_ngram": {
                     "max_gram": 10,
                     "min_gram": 1,
                     "type": "nGram"
                 }
             },
             "analyzer": {
                 "partial": {
                     "filter": [
                         "standard",
                         "lowercase",
                         "asciifolding",
                         "lb_ngram"
                     ],
                     "type": "custom",
                     "tokenizer": "standard"
                 }
             }
         }
     }
 }'

现在,当我添加此映射时:

CURL -XPUT 'http://localhost:9200/test-ngram-7/person/1' -d '{
 "name" : "Cobb",
 "age" : 31
 }'

我可以轻松查询“obb”并获得部分结果。在我的应用程序中,我事先并不知道人们将绘制哪些字段。我显然可以在客户端短路这个并在发布文档之前声明我的映射,但是如果我可以做这样的事情真的很酷:

CURL -XPUT 'http://localhost:9200/test-ngram-7/' -d '{
     "mappings": {
         "person": {
             "properties": {
                 "_default_": {
                     "type": "string",
                     "analyzer": "partial"
                 }
             }
         }
     },
     "settings": {
         "analysis": {
             "filter": {
                 "lb_ngram": {
                     "max_gram": 10,
                     "min_gram": 1,
                     "type": "nGram"
                 }
             },
             "analyzer": {
                 "partial": {
                     "filter": [
                         "standard",
                         "lowercase",
                         "asciifolding",
                         "lb_ngram"
                     ],
                     "type": "custom",
                     "tokenizer": "standard"
                 }
             }
         }
     }
 }'

请注意,我正在使用“默认”。如果我能像“name。*”那样做也很酷,所有以name开头的属性都会以这种方式过滤。我知道elasticsearch支持默认和通配符。*,所以我希望我做错了。

简而言之,我希望新的属性能够在自动创建映射时运行ngram过滤器,而不是使用映射API。

2 个答案:

答案 0 :(得分:1)

您可以设置dynamic_template,有关信息,请参阅http://www.elasticsearch.org/guide/reference/mapping/root-object-type.html

使用此功能,您可以根据匹配,模式匹配等为您未知的字段创建映射模板,并为这些模板应用分析器等。与设置默认分析器相比,这将为您提供更细粒度的行为控制。默认分析器通常应该用于“小写”和“asciifolding”之类的基本内容,但如果您确定要将nGram应用于所有字段,那么它肯定是一种有效的方法。

答案 1 :(得分:0)

所以,我发现的一个解决方案是设置一个“默认”分析器。文档说

  

默认分析器分析器以逻辑名称注册。它   然后可以从映射定义或某些API引用。什么时候   没有定义,使用默认值。有一个选项可以定义   默认情况下,当没有人可以派生时,将使用哪些分析器。

     

默认的逻辑名称允许用户配置分析器   用于索引和搜索API。 default_index   逻辑名称可用于配置默认分析器   仅在索引时使用,并且可以使用default_search   配置将在搜索时使用的默认分析器。

以下是一个例子:

CURL -XPUT 'http://localhost:9200/test-ngram-7/' -d '{

     "settings": {
         "analysis": {
             "filter": {
                 "lb_ngram": {
                     "max_gram": 10,
                     "min_gram": 1,
                     "type": "nGram"
                 }
             },
             "analyzer": {
                 "default": {
                     "filter": [
                         "standard",
                         "lowercase",
                         "asciifolding",
                         "lb_ngram"
                     ],
                     "type": "custom",
                     "tokenizer": "standard"
                 }
             }
         }
     }
 }'

然后此查询将起作用:

CURL -XGET 'http://localhost:9200/test-ngram-7/person/_search' -d '{
  "query":
 {
     "match" : {
         "name" : "obb"
     }
 }
 }'

回答我自己的问题,因为我仍然感兴趣,如果这是“正确”的方式来做到这一点。