如何构建具有 startsWith 功能和特殊字符的 Elasticsearch-Query
How to build an Elasticsearch-Query with startsWith-functionality and special characters
我从 Java 应用程序使用 Elasticsearch 搜索 JsonObjects,使用 Java API 构建搜索查询。这些对象包含一个名为 "such" 的字段,该字段包含一个可以找到 JsonObject 的 searchString,例如,一个简单的 searchString 应该是 "STVBBM160A"。除了常见的字符 a-Z 0-9 之外,searchString 还可能类似于以下示例:
"STV-157ABR"、"F-G/42-W3" 或 "DDM000.074.6652"
当只有第一个字符被放入搜索字段时,搜索应该 return 已经有结果,它对像 "F-G/42"
这样的搜索是这样的
我的问题:搜索有时 return 根本没有结果,但在键入最后一个字符时它会找到正确的文档。
我尝试了什么:首先,我想使用一个 WildcardQuery,其中的查询是 "typedStuff*",但是 WildcardQuery 根本没有 return 任何结果,只要我输入任何东西,但*(它曾经适用于具有其他值的其他搜索字段)
现在我正在使用 QueryStringQuery,它也接受输入并在末尾放置一个 * 字符。通过转义 QueryString,我可以搜索 "F-G/42" 等字符串,但搜索 "DDM000.074.6652" 不会 return 任何结果,直到 elasticsearch 具有要搜索的整个字符串。此外,当我键入 "STV" 时,所有带有 "STV-xxxxx" 的结果(在 STV 后包含“-”)都被 returned,但不是带有 "STVBBM160A" 的对象,直到整个为搜索提供了字符串(搜索字符串为 "STVB" 时不显示任何结果)
这是我现在正在使用的查询:
{
"size": 1000,
"min_score": 1,
"query": {
"bool": {
"must": [
{
"query_string": {
"query": "MY_DATA_TYPE",
"fields": [
"doc.db_doc_type"
]
}
},
{
"query_string": {
"query": "MY_SPECIFIC_TYPE",
"fields": [
"doc.db_doc_specific"
]
}
}
],
"should": {
"query_string": {
"query": "STV*",
"fields": [
"doc.such"
],
"boost": 3,
"escape": true
}
}
}
}
}
这是带有 WildCardQuery 的旧查询,它不会 return 任何结果,除非没有 queryString 但 *:
{
"size": 50,
"min_score": 1,
"query": {
"bool": {
"must": [
{
"query_string": {
"query": "MY_DATA_TYPE",
"fields": [
"doc.db_doc_type"
]
}
},
{
"query_string": {
"query": "MY_SPECIFIC_TYPE",
"fields": [
"doc.db_doc_specific"
]
}
}
],
"should": {
"wildcard": {
"doc.such": {
"wildcard": "STV*",
"boost": 3
}
}
}
}
}
}
使用 PrefixQuery 时,搜索也不会 return 任何结果(有和没有 *):
{
"size": 50,
"min_score": 1,
"query": {
"bool": {
"must": [
{
"query_string": {
"query": "MY_DATA_TYPE",
"fields": [
"doc.db_doc_type"
]
}
},
{
"query_string": {
"query": "MY_SPECIFIC_TYPE",
"fields": [
"doc.db_doc_specific"
]
}
}
],
"should": {
"prefix": {
"doc.such": {
"prefix": "HSTKV*",
"boost": 3
}
}
}
}
}
}
如何更改此查询以实现获取所有以指定字符串开头的结果的目标,无论字段 doc.such 是否还包含数字或特殊字符,如“_”或“。”或“/”?
提前致谢
一旦您想以严肃的方式查询前缀、后缀或子字符串,就需要利用 nGrams。在你的情况下,因为你只是在前缀之后,所以 edgeNGram
tokenizer 是有序的。您需要将索引设置更改为如下所示:
PUT your_index
{
"settings": {
"analysis": {
"analyzer": {
"prefix_analyzer": {
"tokenizer": "prefix_tokenizer",
"filter": [
"lowercase"
]
},
"search_prefix_analyzer": {
"tokenizer": "keyword",
"filter": [
"lowercase"
]
}
},
"tokenizer": {
"prefix_tokenizer": {
"type": "edgeNGram",
"min_gram": "1",
"max_gram": "25"
}
}
}
},
"mappings": {
"your_type": {
"properties": {
"doc": {
"properties": {
"such": {
"type": "string",
"fields": {
"starts_with": {
"type": "string",
"analyzer": "prefix_analyzer",
"search_analyzer": "search_prefix_analyzer"
}
}
}
}
}
}
}
}
}
此分析器将发生的事情是,在索引 F-G/42-W3
时,将索引以下标记:f
、f-
、f-g
、f-g/
, f-g/4
, f-g/42
, f-g/42-
, f-g/42-w
, f-g/42-w3
.
在搜索时,我们将简单地将用户输入小写,前缀将与索引标记匹配。
然后您的查询可以简单地转换为 match
查询:
{
"size": 1000,
"min_score": 1,
"query": {
"bool": {
"must": [
{
"query_string": {
"query": "MY_DATA_TYPE",
"fields": [
"doc.db_doc_type"
]
}
},
{
"query_string": {
"query": "MY_SPECIFIC_TYPE",
"fields": [
"doc.db_doc_specific"
]
}
}
],
"should": {
"match": {
"doc.such": {
"query": "F-G/4"
}
}
}
}
}
}
我从 Java 应用程序使用 Elasticsearch 搜索 JsonObjects,使用 Java API 构建搜索查询。这些对象包含一个名为 "such" 的字段,该字段包含一个可以找到 JsonObject 的 searchString,例如,一个简单的 searchString 应该是 "STVBBM160A"。除了常见的字符 a-Z 0-9 之外,searchString 还可能类似于以下示例: "STV-157ABR"、"F-G/42-W3" 或 "DDM000.074.6652"
当只有第一个字符被放入搜索字段时,搜索应该 return 已经有结果,它对像 "F-G/42"
这样的搜索是这样的我的问题:搜索有时 return 根本没有结果,但在键入最后一个字符时它会找到正确的文档。
我尝试了什么:首先,我想使用一个 WildcardQuery,其中的查询是 "typedStuff*",但是 WildcardQuery 根本没有 return 任何结果,只要我输入任何东西,但*(它曾经适用于具有其他值的其他搜索字段)
现在我正在使用 QueryStringQuery,它也接受输入并在末尾放置一个 * 字符。通过转义 QueryString,我可以搜索 "F-G/42" 等字符串,但搜索 "DDM000.074.6652" 不会 return 任何结果,直到 elasticsearch 具有要搜索的整个字符串。此外,当我键入 "STV" 时,所有带有 "STV-xxxxx" 的结果(在 STV 后包含“-”)都被 returned,但不是带有 "STVBBM160A" 的对象,直到整个为搜索提供了字符串(搜索字符串为 "STVB" 时不显示任何结果)
这是我现在正在使用的查询:
{
"size": 1000,
"min_score": 1,
"query": {
"bool": {
"must": [
{
"query_string": {
"query": "MY_DATA_TYPE",
"fields": [
"doc.db_doc_type"
]
}
},
{
"query_string": {
"query": "MY_SPECIFIC_TYPE",
"fields": [
"doc.db_doc_specific"
]
}
}
],
"should": {
"query_string": {
"query": "STV*",
"fields": [
"doc.such"
],
"boost": 3,
"escape": true
}
}
}
}
}
这是带有 WildCardQuery 的旧查询,它不会 return 任何结果,除非没有 queryString 但 *:
{
"size": 50,
"min_score": 1,
"query": {
"bool": {
"must": [
{
"query_string": {
"query": "MY_DATA_TYPE",
"fields": [
"doc.db_doc_type"
]
}
},
{
"query_string": {
"query": "MY_SPECIFIC_TYPE",
"fields": [
"doc.db_doc_specific"
]
}
}
],
"should": {
"wildcard": {
"doc.such": {
"wildcard": "STV*",
"boost": 3
}
}
}
}
}
}
使用 PrefixQuery 时,搜索也不会 return 任何结果(有和没有 *):
{
"size": 50,
"min_score": 1,
"query": {
"bool": {
"must": [
{
"query_string": {
"query": "MY_DATA_TYPE",
"fields": [
"doc.db_doc_type"
]
}
},
{
"query_string": {
"query": "MY_SPECIFIC_TYPE",
"fields": [
"doc.db_doc_specific"
]
}
}
],
"should": {
"prefix": {
"doc.such": {
"prefix": "HSTKV*",
"boost": 3
}
}
}
}
}
}
如何更改此查询以实现获取所有以指定字符串开头的结果的目标,无论字段 doc.such 是否还包含数字或特殊字符,如“_”或“。”或“/”?
提前致谢
一旦您想以严肃的方式查询前缀、后缀或子字符串,就需要利用 nGrams。在你的情况下,因为你只是在前缀之后,所以 edgeNGram
tokenizer 是有序的。您需要将索引设置更改为如下所示:
PUT your_index
{
"settings": {
"analysis": {
"analyzer": {
"prefix_analyzer": {
"tokenizer": "prefix_tokenizer",
"filter": [
"lowercase"
]
},
"search_prefix_analyzer": {
"tokenizer": "keyword",
"filter": [
"lowercase"
]
}
},
"tokenizer": {
"prefix_tokenizer": {
"type": "edgeNGram",
"min_gram": "1",
"max_gram": "25"
}
}
}
},
"mappings": {
"your_type": {
"properties": {
"doc": {
"properties": {
"such": {
"type": "string",
"fields": {
"starts_with": {
"type": "string",
"analyzer": "prefix_analyzer",
"search_analyzer": "search_prefix_analyzer"
}
}
}
}
}
}
}
}
}
此分析器将发生的事情是,在索引 F-G/42-W3
时,将索引以下标记:f
、f-
、f-g
、f-g/
, f-g/4
, f-g/42
, f-g/42-
, f-g/42-w
, f-g/42-w3
.
在搜索时,我们将简单地将用户输入小写,前缀将与索引标记匹配。
然后您的查询可以简单地转换为 match
查询:
{
"size": 1000,
"min_score": 1,
"query": {
"bool": {
"must": [
{
"query_string": {
"query": "MY_DATA_TYPE",
"fields": [
"doc.db_doc_type"
]
}
},
{
"query_string": {
"query": "MY_SPECIFIC_TYPE",
"fields": [
"doc.db_doc_specific"
]
}
}
],
"should": {
"match": {
"doc.such": {
"query": "F-G/4"
}
}
}
}
}
}