我们正在将搜索策略从数据库迁移到ElasticSearch。在此期间,我们需要保留现有功能,部分搜索类似于以下SQL查询的字段(包括空格):
SELECT *
FROM customer
WHERE customer_id LIKE '%0995%';
话虽如此,我已经阅读了与ES相关的多篇文章并实现了上述功能。完成上述练习后,我将提出以下建议:
注意: customer_id字段的最大长度为VARCHAR2(100)。
{
"customer-index":{
"aliases":{
},
"mappings":{
"customer":{
"properties":{
"customerName":{
"type":"text",
"fields":{
"keyword":{
"type":"keyword",
"ignore_above":256
}
}
},
"customerId":{
"type":"text",
"fields":{
"keyword":{
"type":"keyword",
"ignore_above":256
}
},
"analyzer":"substring_analyzer"
}
}
}
},
"settings":{
"index":{
"number_of_shards":"3",
"provided_name":"customer-index",
"creation_date":"1573333835055",
"analysis":{
"filter":{
"substring":{
"type":"ngram",
"min_gram":"3",
"max_gram":"100"
}
},
"analyzer":{
"substring_analyzer":{
"filter":[
"lowercase",
"substring"
],
"type":"custom",
"tokenizer":"standard"
}
}
},
"number_of_replicas":"1",
"uuid":"XXXXXXXXXXXXXXXXX",
"version":{
"created":"5061699"
}
}
}
}
}
查询数据的请求看起来像这样:
{
"from": 0,
"size": 10,
"sort": [
{
"name.keyword": {
"missing": "_first",
"order": "asc"
}
}
],
"query": {
"bool": {
"filter": [
{
"query_string": {
"query": "0995",
"fields": [
"customer_id"
],
"analyzer": "substring_analyzer"
}
}
]
}
}
}
话虽如此,这是几个查询/问题:
0009950011214, 0009900011214, 0009920011214
当我搜索“ 0995”时。理想情况下,我希望只获得customer_id:0009950011214。
但是我将所有三个记录作为结果集的一部分,我相信这归因于nGram分析器及其拆分字符串的方式(请注意:minGram:3和maxGram:100)。将maxGram设置为100是为了完全匹配。
我该如何解决?
P.S:我使用的是NEST 5.5。
答案 0 :(得分:0)
从映射中,我可以看到字段customerId是文本/关键字字段。(Difference between keyword and text in ElasticSearch) 因此,您可以使用如下所示的正则表达式过滤器进行搜索,就像您作为示例给出的sql查询一样,请尝试-
{
"query": {
"constant_score": {
"filter": {
"bool": {
"must": [
{
"regexp": {
"customerId": {
"value": ".*0995.*",
"flags": "ALL"
}
}
}
]
}
}
}
}
}
请注意正则表达式的值中的“。”。 。。*与包含搜索相同 〜(。。)等于不包含 您还可以在搜索词的开头或结尾处添加“。*”,以执行诸如Ends-with和Starts-with之类的搜索。参考-https://www.elastic.co/guide/en/elasticsearch/reference/6.4/query-dsl-regexp-query.html
答案 1 :(得分:0)
在您的customerID字段中,您可以传递"search_analyzer": "standard"
。然后在搜索查询中删除行"analyzer": "substring_analyzer"
。
这将确保搜索到的客户ID不会被标记为nGrams并按原样进行搜索,而客户ID被索引为nGrams。 我相信这就是您试图从SQL查询中复制的功能。