【问题标题】:Wildcard doesn't work as expected when querying by more than a word查询多个单词时,通配符无法按预期工作
【发布时间】:2019-01-28 19:43:50
【问题描述】:

如果我在“消息”字段中搜索包含例如“被调用”的文档,我会得到预期的结果,但是当我搜索“被调用”、“被调用*”或

"*was called*"

我什么也没得到,尽管我有很多文档,其消息字段包含以下内容“应用程序被 REST API 调用”。

这是我发送的查询的一部分:

"wildcard": {
    "message": {
        "wildcard": "was called",
        "boost": 1.0
    }
}

这是映射的一部分:

"mappings": {
    "doc": {
        "dynamic_templates": [
            {
                "message_field": {
                    "path_match": "message",
                    "match_mapping_type": "string",
                    "mapping": {
                        "norms": false,
                        "type": "text"
                    }
                }
            },
            {
                "string_fields": {
                    "match": "*",
                    "match_mapping_type": "string",
                    "mapping": {
                        "fields": {
                            "keyword": {
                                "ignore_above": 256,
                                "type": "keyword"
                            }
                        },
                        "norms": false,
                        "type": "text"
                    }
                }
            }
        ],
        "properties": {
            ...
            "message": {
                "type": "text",
                "norms": false
            }
        }
    }
}

我搜索的索引是由 Logstash 自动创建的。

我在另一个领域也有类似的问题;我在该字段中有以下值:“NP-00121”。 *00121 有效,但 *-00121 无效。

编辑:还有一个示例:当我发送以下通配符查询时,我有一个包含“/api/v1/log/rest”、“/api/v1/log/notification”等的“requestUri”字段没有“/api/v1*”。

所以看起来在使用空格和破折号时会出现问题。谁能帮我解决这个问题?

【问题讨论】:

  • 正如您在通配符查询文档中所读到的,将通配符用作前缀是一种非常糟糕的做法。您应该考虑使用 ngrams,这里有一个广泛的问答,展示了如何做到这一点(我曾经遇到过同样的问题):stackoverflow.com/questions/30666371/…
  • 感谢您的回答,但我不知道您在哪里看到前缀。我相信 ngrams 不是解决方案。我可以使用带有 AND 运算符的匹配查询来代替通配符查询,但这不是一个很好的解决方案。现在我将添加另一个示例,可以进一步澄清我遇到的问题
  • 使用通配符* 作为前缀(如*00121)是一种不好的做法,这就是我所指的。无论何时寻找部分单词,无论是在开头还是结尾,ngram 都是解决方案。
  • 我想应该在 Elastic 搜索服务器上定义 ngram?我的索引是由 logstash 自动创建的(新的一天 - 新的索引)。
  • 您可以定义一个index template,其中包含进行 ngram 标记化所需的分析器。因此,每天当 logstash 创建新索引时,可以将适当的索引设置/分析器应用于您的索引。

标签: elasticsearch lucene logstash


【解决方案1】:

通配符在标记中使用。您的消息字段被索引为文本,因此将被标记为单词。

基本上,对于“被调用”之类的查询,您不需要通配符。只需使用 phrase query 即可:

"query": {
    "match_phrase" : {
        "message" : "was called"
    }
}

或者如果你更喜欢query string query:

"query": {
    "query_string" : {
        "query" : "message:\"was called\""
    }
}

通配符查询对于搜索部分术语很有用,例如:

"query": {
    "wildcard" : { "message" : "call*" }
}

如果您想查找所有包含“call”、“calling”或“calling”的文档。


对于像 NP-00121 这样的值或 URI,如果不分析这些字段可能会更有用。因为这些被分成令牌('np'和'00121'),所以你看到的问题。您可以将这些字段索引为 "keyword" 类型而不是“文本”,以便将整个字段索引为单个未分析的标记。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-06
    • 2017-09-19
    • 2018-10-13
    相关资源
    最近更新 更多