如何使用startsWith功能和特殊字符

时间:2017-01-17 15:43:28

标签: java elasticsearch wildcard

我有JsonObjects,我从Java应用程序中搜索Elasticsearch,使用Java API构建searchQueries。这些对象包含一个名为&#34的字段;例如"它包含一个searchString,用于找到JsonObject,例如一个简单的searchString将是" STVBBM160A"。除了通常的字符a-Z 0-9之外,searchString也可能类似于以下示例: " STV-157ABR"," F-G / 42-W3"或" DDM000.074.6652"

当只有第一个字符被放入搜索字段时,搜索应该返回结果,这对搜索类似于" F-G / 42"

我的问题:搜索有时根本不会返回结果,但是当输入最后一个字符时,它会找到正确的文档。

我尝试过:首先我想使用一个WildcardQuery,其中查询将是" typedStuff *",但是只要我键入任何内容,WildcardQuery就不会返回任何结果但是*(它曾用于其他具有其他值的searchFields)

现在我正在使用QueryStringQuery,它还接受输入并将*字符放到最后。通过转义QueryString,我可以搜索" F-G / 42"等字符串。等等,但搜索" DDM000.074.6652"在elasticsearch拥有要搜索的整个String之前,不会返回任何结果。此外,当我输入" STV"所有结果与" STV-xxxxx" (包含" - "在STV之后)返回,但不是带有" STVBBM160A"的对象,直到为搜索提供整个字符串(没有在中间显示任何结果)因为searchString是" 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的旧查询,除非没有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时,搜索也不会返回任何结果(使用和不使用*):

{
  "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是否还包含数字或特殊字符,如" _"或"。"或" /" ?

提前致谢

1 个答案:

答案 0 :(得分:1)

只要您想以严肃的方式查询前缀,后缀或子字符串,就需要利用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/,{ {1}},f-g/4f-g/42f-g/42-f-g/42-w

在搜索时,我们只是小写用户输入,前缀将与索引标记匹配。

然后您的查询可以简单地转换为f-g/42-w3查询:

match