在not_analyzed字段上进行Elasticsearch通配符搜索

Hüs*_*BAL 7 lucene search tokenize elasticsearch

我有一个索引,如下面的设置和映射;

{
  "settings":{
     "index":{
        "analysis":{
           "analyzer":{
              "analyzer_keyword":{
                 "tokenizer":"keyword",
                 "filter":"lowercase"
              }
           }
        }
     }
  },
  "mappings":{
     "product":{
        "properties":{
           "name":{
              "analyzer":"analyzer_keyword",
              "type":"string",
              "index": "not_analyzed"
           }
        }
     }
  }
}
Run Code Online (Sandbox Code Playgroud)

我正在努力为name字段上的通配符搜索实现.我的示例数据是这样的;

[
{"name": "SVF-123"},
{"name": "SVF-234"}
]
Run Code Online (Sandbox Code Playgroud)

当我执行以下查询时;

http://localhost:9200/my_index/product/_search -d '
{
    "query": {
        "filtered" : {
            "query" : {
                "query_string" : {
                    "query": "*SVF-1*"
                }
            }
        }

    }
}'
Run Code Online (Sandbox Code Playgroud)

它返回SVF-123,SVF-234.我认为,它仍然是数据的标记.它必须只返回SVF-123.

你能帮忙吗?

提前致谢

Ale*_*vik 14

这里有一些问题.

首先,您说您不希望术语分析索引时间.然后,配置了一个分析器(用于搜索时间),生成不兼容的术语.(他们是小写的)

默认情况下,所有术语都_all使用标准分析器在-field中结束.那是你最终搜索的地方.由于它在" - "上标记,因此最终得到"*SVF"和"1*"的OR.

尝试在_all和name上做一个术语方面,看看发生了什么.

这是一个可运行的游戏和要点:https://www.found.no/play/gist/3e5fcb1b4c41cfc20226(https://gist.github.com/alexbrasetvik/3e5fcb1b4c41cfc20226)

您需要确保索引的术语与您搜索的内容兼容.你可能想要禁用_all,因为它可能会使正在发生的事情变得混乱.

#!/bin/bash

export ELASTICSEARCH_ENDPOINT="http://localhost:9200"

# Create indexes

curl -XPUT "$ELASTICSEARCH_ENDPOINT/play" -d '{
    "settings": {
        "analysis": {
            "text": [
                "SVF-123",
                "SVF-234"
            ],
            "analyzer": {
                "analyzer_keyword": {
                    "type": "custom",
                    "tokenizer": "keyword",
                    "filter": [
                        "lowercase"
                    ]
                }
            }
        }
    },
    "mappings": {
        "type": {
            "properties": {
                "name": {
                    "type": "string",
                    "index": "not_analyzed",
                    "analyzer": "analyzer_keyword"
                }
            }
        }
    }
}'


# Index documents
curl -XPOST "$ELASTICSEARCH_ENDPOINT/_bulk?refresh=true" -d '
{"index":{"_index":"play","_type":"type"}}
{"name":"SVF-123"}
{"index":{"_index":"play","_type":"type"}}
{"name":"SVF-234"}
'

# Do searches

# See all the generated terms.
curl -XPOST "$ELASTICSEARCH_ENDPOINT/_search?pretty" -d '
{
    "facets": {
        "name": {
            "terms": {
                "field": "name"
            }
        },
        "_all": {
            "terms": {
                "field": "_all"
            }
        }
    }
}
'

# Analyzed, so no match
curl -XPOST "$ELASTICSEARCH_ENDPOINT/_search?pretty" -d '
{
    "query": {
        "match": {
            "name": {
                "query": "SVF-123"
            }
        }
    }
}
'

# Not analyzed according to `analyzer_keyword`, so matches. (Note: term, not match)
curl -XPOST "$ELASTICSEARCH_ENDPOINT/_search?pretty" -d '
{
    "query": {
        "term": {
            "name": {
                "value": "SVF-123"
            }
        }
    }
}
'


curl -XPOST "$ELASTICSEARCH_ENDPOINT/_search?pretty" -d '
{
    "query": {
        "term": {
            "_all": {
                "value": "svf"
            }
        }
    }
}
'
Run Code Online (Sandbox Code Playgroud)


Hüs*_*BAL 11

我的解决方案冒险

我已经开始了我的案子,你可以在我的问题中看到.每当我更改了部分设置时,一部分开始工作,但另一部分停止工作.让我给出我的解决方案历史:

1.)我已将我的数据编入索引为默认值.这意味着,我的数据是analyzed默认的.这会引起我的问​​题.例如;

当用户开始搜索SVF-1之类的关键字时,系统会运行以下查询:

{
    "query": {
        "filtered" : {
            "query" : {
                "query_string" : {
                    "analyze_wildcard": true,
                    "query": "*SVF-1*"
                }
            }
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

和结果;

SVF-123
SVF-234
Run Code Online (Sandbox Code Playgroud)

这是正常的,因为name我的文件的字段是analyzed.这种分裂查询分成记号SVF,并1SVF我的文档匹配,即使1不匹配.我已经跳过了这种方式.我为我的字段创建了一个映射not_analyzed

{
  "mappings":{
     "product":{
        "properties":{
           "name":{
              "type":"string",
              "index": "not_analyzed"
           },
           "site":{
              "type":"string",
              "index": "not_analyzed"
           } 
        }
     }
  }
}
Run Code Online (Sandbox Code Playgroud)

但我的问题还在继续.

2.)经过大量研究,我想尝试另一种方式.决定使用通配符查询.我的疑问是;

{
    "query": {
        "wildcard" : {
            "name" : {
                "value" : *SVF-1*"
             }
          }
      },
            "filter":{
                    "term": {"site":"pro_en_GB"}
            }
    }
}
Run Code Online (Sandbox Code Playgroud)

这个查询有效,但这里有一个问题.我的字段不再被分析,我正在进行通配符查询.区分大小写是一个问题.如果我像svf-1一样搜索,它什么都不返回.因为,用户可以输入小写版本的查询.

3.)我已将文档结构更改为;

{
  "mappings":{
     "product":{
        "properties":{
           "name":{
              "type":"string",
              "index": "not_analyzed"
           },
           "nameLowerCase":{
              "type":"string",
              "index": "not_analyzed"
           }
           "site":{
              "type":"string",
              "index": "not_analyzed"
           } 
        }
     }
  }
}
Run Code Online (Sandbox Code Playgroud)

我已经再加上一个字段用于name调用nameLowerCase.当我索引我的文档时,我正在设置我的文档;

{
    name: "SVF-123",
    nameLowerCase: "svf-123",
    site: "pro_en_GB"
}
Run Code Online (Sandbox Code Playgroud)

在这里,我将查询关键字转换为小写,并对新nameLowerCase索引进行搜索操作.并显示name字段.

我的查询的最终版本是;

{
    "query": {
        "wildcard" : {
            "nameLowerCase" : {
                "value" : "*svf-1*"
             }
          }
      },
            "filter":{
                    "term": {"site":"pro_en_GB"}
            }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在它有效.使用multi_field还有一种方法可以解决这个问题.我的查询包含破折号( - ),并遇到一些问题.

非常感谢@Alex Brasetvik的详细解释和努力