如何构建具有 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 时,将索引以下标记:ff-f-gf-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"
          }
        }
      }
    }
  }
}