【问题标题】:Search for exact phrase with Elasticsearch使用 Elasticsearch 搜索准确的短语
【发布时间】:2017-11-10 12:01:33
【问题描述】:

我目前开始使用 Elasticsearch。我已经索引了一些 EDIFACT 消息(一种史前数据格式;-) 内容如下所示:

UNB+UNOA:2+SENDER+RECEIVER+170509:0050+152538'
UNH+66304+CODECO:D:95B:UN:ITG12'
BGM+34+INGATE OF UCN ABCD+9'

当我搜索短语 UNH+66304+CODECO:D:95B 时,它应该只返回一次命中,但似乎它正在返回包含这些单词中的任何一个的所有文件(并且 UNH 在每个文件)。 我的查询是这样的:

curl -XGET --netrc-file ~/curl_user  'localhost:9200/edi/message/_search?pretty' -H 'Content-Type: application/json' -d'
{
    "query":{
        "match":{"MESSAGE":"UNH+66304+CODECO:D:95B"}
    }
}'

我尝试像这样添加“and”运算符:

"match":{
              "MESSAGE":{
                "query":"UNH+66304+CODECO",
                "operator": "and"

              }
            }

但是没有返回任何结果。 我在这里阅读了建议:Searching for exact phrase 我需要使用双引号。 "query":"'UNH+66304+CODECO'" 和 "query":"\"UNH+66304+CODECO\"" 我都试过了,但没有任何区别。

我也试过 match_phrase

"match_phrase":{
              "MESSAGE":{
                "query":"UNH+66304+CODECO"

              }
            }

不返回结果

"match_phrase":{
              "MESSAGE":{
                "query":"UNH+66304"

              }
            }

确实如此。 对于普通文本,它似乎可以工作,但不知何故,Elasticsearch 不喜欢在搜索字符串中使用 +: 等(不幸的是,这是 EDIFACT 的一部分)。

How to make query_string search exact phrase in ElasticSearch 谈到如果您想要完全匹配使用不同的分析器?

更新: abhishek mishra 确认分析器可能是要走的路。我使用的是 Elasticsearch 5.4,有很多分析器可供选择:https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-analyzers.html

关键字分析器可能会映射到 abhishek 建议的“未分析”,因为它是一个 noop 分析器。但是我有点担心使用它,因为消息可能会很长。搜索对性能有何影响?如果我使用关键字分析器,我仍然可以搜索整封邮件的部分内容吗?

我想知道模式分析器是否适合? EDIFACT 消息由以 3 个大写字符开头并以 ' 结尾的段组成(但您可以通过在其前面加上 ? 来转义 ')

FTX+AAA++It?'s a strange data format'
FTX+AAA++Yes it is'

所以上面的例子是两个段。如果我将使用分隔这些段的模式,那会是一个很好的匹配吗?

唯一的问题是当前 MESSAGE 字段可以包含 EDIFACT 消息和 XML 消息。我想使用相同的模式分析器是行不通的,所以我必须根据 MESSAGE 字段的内容创建两种不同的类型(其余的都是相同的)。

第二次更新: 我已按照建议研究分析仪。我认为关键字分析器可能不是一个好主意,因为文本可能很长。我发现模式分析器(没有任何自定义模式)工作得很好。它将所有内容拆分为:和+。类似的搜索

{
    "query":{
        "match_phrase":{"MESSAGE":"RFF+ABT:ATB150538080520172452"}
    }
}

{
        "query":{
            "match_phrase":{"MESSAGE":"RFF+ABT:ATB150538080520172452"}
        }
    }

现在开始工作。之前的问题是,例如被分成 [rff,abt:atb150538080520172452]。

【问题讨论】:

    标签: elasticsearch edifact


    【解决方案1】:

    您对分析仪的看法是正确的。如果您查看您的类型映射,属性MESSAGE 可能标记为analyzed。这就是为什么在索引时它会摆脱特殊字符。您需要将其标记为not_analyzed

    如果您让我们知道您的类型映射是什么样的,我可以帮助您进行正确的设置。

    其中一个例子-

    如果你的 ES 版本是

    {
    
      "MESSAGE": {
        "type" "string",
        "index": "analyzed"
      }
    }
    

    改成

    {
      "MESSAGE": {
        "type" "string",
        "index": "not_analyzed"
      }
    }
    

    【讨论】:

    • 感谢您的建议,我使用的是 Elasticsearch 5.4,似乎 API 发生了变化,从现在开始有更多分析器可供选择。我将更新关于分析仪的问题。
    • 太棒了。那么,它现在有效吗?如果是,那么我相信您可以为自己的问题提供答案。它对其他人有用。
    【解决方案2】:

    解决方案是使用模式分析器。无需进一步配置(未指定自定义模式),它将 EDIFACT 消息分解为非单词/数字字符。

    标准分析器的问题在于它与 ':' 的行为很奇怪。 所以如果你例如有 RFF+ATB:AB12345;它将其分解为 [rff, atb:ab12345] 因此搜索 ab12345 没有返回任何内容。

    您可以通过使用测试分析器或标记器的工作方式

    curl -XPOST --netrc-file ~/curl_user 'localhost:9200/_analyze?pretty' -H 'Content-Type: application/json' -d'
    {
      "analyzer": "standard",
      "text":      "UNB+UNOA:2+SENDER+RECEIVER+170513:0452+129910165"
    }'
    

    如果您只想测试使用的分词器,可以将“分析器”替换为分词器。

    【讨论】:

      【解决方案3】:

      我认为您将“查询”和“匹配短语”颠倒了:

      你可以这样试试吗:

      {
          "query": {
              "match_phrase": {
                  "MESSAGE": "UNH+66304"
              }
          }
      }
      

      【讨论】:

      • 如果您查看我的第一个示例,您会看到这一点。其他代码示例省略了第一个“查询”以缩短帖子(但仍在测试中使用)。如果您想指定更多(例如运算符),您可以有一个“第二个”“查询”。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-31
      • 1970-01-01
      • 1970-01-01
      • 2021-08-19
      • 1970-01-01
      • 2011-07-28
      • 1970-01-01
      相关资源
      最近更新 更多