2015-06-04 71 views
3

我正在尝试创建一个搜索栏,其中最常见的查询将是“serviceOrderNo”。 “serviceOrderNo”不是数据库中的号码字段,它是字符串字段。示例:用Elasticsearch忽略前导零

000000007 
000000002 
WO0000042 
123456789 
AllTextss 
000000054 
000000065 
000000874 

最常见的格式只是一个由一定数量的零开始的整数。

如何设置Elasticsearch以便搜索“65”将匹配“000000065”?我也想优先考虑“serviceOrderNo”字段(我已经工作了)。下面是我在目前位置:

这样做是使用Lucene的味道经常exression查询
{ 
    "query": { 
     "multi_match": { 
     "query": "65", 
     "fields": ["serviceOrderNo^2", "_all"], 
     } 
    } 
} 

回答

6

方式一:

https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-regexp-query.html

"query": { 
    "regexp":{ 
     "serviceOrderNo": "[0]*65" 
    } 
} 

此外,查询字符串查询还支持一小组特殊字符,更多有限的正则表达式字符集,AS以及lucene正则表达式,查询将如下所示: https://www.elastic.co/guide/en/elasticsearch/reference/1.x/query-dsl-query-string-query.html

"query": { 
    "query_string": { 
     "default_field": "serviceOrderNo", 
     "query": "0*65" 
    } 
} 

这些都是相当简单的正则表达式,都称符合包含在括号[0]或字符0无限次*字符(S)。

如果您有能力重新编制索引或尚未编制数据索引,您还可以通过编写自定义分析器来简化自己的工作。现在,您正在serviceOrderNo字段中使用字符串的默认分析器。当您索引"serviceOrderNo":"00000065"时,ES将其解释为00000065.

您的自定义分析器可以使用相同的正则表达式将此字段标记为“0000065”和“65”两者。这样做的好处是,正则表达式只在索引时运行一次,而不是每次运行查询时,因为ES将同时针对“0000065”和“65”进行搜索。

您还可以检出the ES website documentation on Analyzers。要做到这一点

"settings":{ 
    "analysis": { 
     "filter":{ 
      "trimZero": { 
       "type":"pattern_capture", 
       "patterns":"^0*([0-9]*$)" 
      } 
     }, 
     "analyzer": { 
      "serviceOrderNo":{ 
       "type":"custom", 
       "tokenizer":"standard", 
       "filter":"trimZero" 
      } 
     } 
    } 
}, 
"mappings":{ 
    "serviceorderdto": { 
     "properties":{ 
      "serviceOrderNo":{ 
       "type":"String", 
       "analyzer":"serviceOrderNo" 
      } 
     } 
    } 
} 
+1

我才意识到我确实写的正则表达式自定义分析的真懒工作。我已经用三次测试的接班人更新了我的答案。 – IanGabes

+0

我试过你的解决方案,它工作。谢谢!我正处于建立ES的早期阶段,所以我可以重新编制索引,因此您的解决方案运行良好。我也发布了一个不同的答案,但不确定我们要去哪一个。如果您发现ngram解决方案的任何缺点,请发表评论。 –

0

的一种方法是使用一个ngram token filter,使“12345”被符号化如下:

[ 1, 2, 3, 4, 5 ] 
[ 12, 23, 34, 45 ] 
[ 123, 234, 345 ] 
[ 12345 ] 

当记号化这种方式,“65”是一个匹配“000000065”。

要这样设置,创建有一个使用NGRAM过滤器自定义分析的新指标:

POST /my-index 
{ 
    "mappings": { 
     "serviceorderdto": { 
     "properties": { 
      "serviceOrderNo": { 
       "type": "string", 
       "analyzer": "autocomplete" 
      } 
     } 
     } 
    }, 
    "settings": { 
     "analysis": { 
     "filter": { 
      "autocomplete_filter": { 
       "type": "ngram", 
       "min_gram": 1, 
       "max_gram": 20 
      } 
     }, 
     "analyzer": { 
      "autocomplete": { 
       "type": "custom", 
       "tokenizer": "standard", 
       "filter": [ 
        "lowercase", 
        "autocomplete_filter" 
       ] 
      } 
     } 
     } 
    } 
} 

指数的一些数据。 然后运行查询:

GET /my-index/_search 
{ 
    "query": { 
     "multi_match": { 
      "query": "55", 
      "fields": [ 
       "serviceOrderNo^2", 
       "_all" 
      ] 
     } 
    } 
}