【问题标题】:Elasticsearch not returning an exact match firstElasticsearch 没有首先返回完全匹配
【发布时间】:2023-04-09 06:02:01
【问题描述】:

我有一个带有精确匹配字段的弹性搜索索引,不知何故我得到了很多相似的结果(我不介意),并且这些相似的结果在完全匹配之前排序,(我这样做记住。)

有人可以解释发生了什么以及如何解决它吗?

我的映射是这样的

"exact":{
  "type":"string",
  "boost":10.0,
  "analyzer":"keyword"
},

我搜索“AAPL P JAN 2014 885,00”的查询是这样的:

{
  "size" : 21,
  "query" : {
    "field" : {
      "exact" : "AAPL P JAN 2014 885,00"
    }
  },
  "explain" : true,
  "sort" : [ {
    "_score" : {
      "order" : "desc"
    }
  } ],
  "facets" : {
    "category" : {
      "terms" : {
        "field" : "category",
        "size" : 10
      }
    }
  }
}

返回的文档按以下顺序结束:

  • {"exact":["APPLE INC","US0378331005","AAPL","73773"],"id-compound":"AAPL"}
  • {"exact":["AAPL","73773","AAPL P JAN 2014 675,00"],"id-compound":"AAPL*PUT*20140118*675"}
  • {"exact":["AAPL","73773","AAPL C JAN 2014 500,00"],"id-compound":"AAPL*CALL*20140118*500"}

等,完全匹配一系列结果。

有人可以向我解释为什么完全匹配没有在顶部结束吗?

如果有助于理解,下面是带有完整解释的搜索结果。

"hits" : [ {
  "_shard" : 0,
  "_node" : "1",
  "_index" : "instruments",
  "_type" : "instrument",
  "_id" : "AAPL",
  "_score" : 1306.8339, "_source" : {"exact":["APPLE INC","US0378331005","AAPL","73773"],"id-compound":"AAPL"},
  "_explanation" : {
    "value" : 1306.8339,
    "description" : "product of:",
    "details" : [ {
      "value" : 6534.169,
      "description" : "sum of:",
      "details" : [ {
        "value" : 6534.169,
        "description" : "weight(exact:AAPL in 9096), product of:",
        "details" : [ {
          "value" : 0.25854474,
          "description" : "queryWeight(exact:AAPL), product of:",
          "details" : [ {
            "value" : 6.1701355,
            "description" : "idf(docFreq=211, maxDocs=37299)"
          }, {
            "value" : 0.0419026,
            "description" : "queryNorm"
          } ]
        }, {
          "value" : 25272.875,
          "description" : "fieldWeight(exact:AAPL in 9096), product of:",
          "details" : [ {
            "value" : 1.0,
            "description" : "tf(termFreq(exact:AAPL)=1)"
          }, {
            "value" : 6.1701355,
            "description" : "idf(docFreq=211, maxDocs=37299)"
          }, {
            "value" : 4096.0,
            "description" : "fieldNorm(field=exact, doc=9096)"
          } ]
        } ]
      } ]
    }, {
      "value" : 0.2,
      "description" : "coord(1/5)"
    } ]
  }
}, {
  "_shard" : 0,
  "_node" : "1",
  "_index" : "instruments",
  "_type" : "instrument",
  "_id" : "AAPL*PUT*20140118*675",
  "_score" : 163.35423, "_source" : {"exact":["AAPL","73773","AAPL P JAN 2014 675,00"],"id-compound":"AAPL*PUT*20140118*675"},
  "_explanation" : {
    "value" : 163.35423,
    "description" : "product of:",
    "details" : [ {
      "value" : 816.7711,
      "description" : "sum of:",
      "details" : [ {
        "value" : 816.7711,
        "description" : "weight(exact:AAPL in 18), product of:",
        "details" : [ {
          "value" : 0.25854474,
          "description" : "queryWeight(exact:AAPL), product of:",
          "details" : [ {
            "value" : 6.1701355,
            "description" : "idf(docFreq=211, maxDocs=37299)"
          }, {
            "value" : 0.0419026,
            "description" : "queryNorm"
          } ]
        }, {
          "value" : 3159.1094,
          "description" : "fieldWeight(exact:AAPL in 18), product of:",
          "details" : [ {
            "value" : 1.0,
            "description" : "tf(termFreq(exact:AAPL)=1)"
          }, {
            "value" : 6.1701355,
            "description" : "idf(docFreq=211, maxDocs=37299)"
          }, {
            "value" : 512.0,
            "description" : "fieldNorm(field=exact, doc=18)"
          } ]
        } ]
      } ]
    }, {
      "value" : 0.2,
      "description" : "coord(1/5)"
    } ]
  }
}, {
  "_shard" : 0,
  "_node" : "1",
  "_index" : "instruments",
  "_type" : "instrument",
  "_id" : "AAPL*CALL*20140118*500",
  "_score" : 163.35423, "_source" : {"exact":["AAPL","73773","AAPL C JAN 2014 500,00"],"id-compound":"AAPL*CALL*20140118*500"},
  "_explanation" : {
    "value" : 163.35423,
    "description" : "product of:",
    "details" : [ {
      "value" : 816.7711,
      "description" : "sum of:",
      "details" : [ {
        "value" : 816.7711,
        "description" : "weight(exact:AAPL in 383), product of:",
        "details" : [ {
          "value" : 0.25854474,
          "description" : "queryWeight(exact:AAPL), product of:",
          "details" : [ {
            "value" : 6.1701355,
            "description" : "idf(docFreq=211, maxDocs=37299)"
          }, {
            "value" : 0.0419026,
            "description" : "queryNorm"
          } ]
        }, {
          "value" : 3159.1094,
          "description" : "fieldWeight(exact:AAPL in 383), product of:",
          "details" : [ {
            "value" : 1.0,
            "description" : "tf(termFreq(exact:AAPL)=1)"
          }, {
            "value" : 6.1701355,
            "description" : "idf(docFreq=211, maxDocs=37299)"
          }, {
            "value" : 512.0,
            "description" : "fieldNorm(field=exact, doc=383)"
          } ]
        } ]
      } ]
    }, {
      "value" : 0.2,
      "description" : "coord(1/5)"
    } ]
  }
}, {
  "_id" : "AAPL*PUT*20140118*940",
  "_score" : 163.35423, "_source" : {"exact":["AAPL","73773","AAPL P JAN 2014 940,00"],"id-compound":"AAPL*PUT*20140118*940"},
  "_explanation" : {
    "value" : 163.35423,
    "description" : "product of:",
    "details" : [ {
      "value" : 816.7711,
      "description" : "sum of:",
      "details" : [ {
        "value" : 816.7711,
        "description" : "weight(exact:AAPL in 794), product of:",
        "details" : [ {
          "value" : 0.25854474,
          "description" : "queryWeight(exact:AAPL), product of:",
          "details" : [ {
            "value" : 6.1701355,
            "description" : "idf(docFreq=211, maxDocs=37299)"
          }, {
            "value" : 0.0419026,
            "description" : "queryNorm"
          } ]
        }, {
          "value" : 3159.1094,
          "description" : "fieldWeight(exact:AAPL in 794), product of:",
          "details" : [ {
            "value" : 1.0,
            "description" : "tf(termFreq(exact:AAPL)=1)"
          }, {
            "value" : 6.1701355,
            "description" : "idf(docFreq=211, maxDocs=37299)"
          }, {
            "value" : 512.0,
            "description" : "fieldNorm(field=exact, doc=794)"
          } ]
        } ]
      } ]
    }, {
      "value" : 0.2,
      "description" : "coord(1/5)"
    } ]
  }
}

如果我分析我要存储的数据会发生什么情况:

curl -XGET 'localhost:9200/instruments/_analyze?field=exact&pretty=true' -d 'ING  P JUN 2013 6.00'
{
  "tokens" : [ {
    "token" : "ING  P JUN 2013 6.00",
    "start_offset" : 0,
    "end_offset" : 20,
    "type" : "word",
    "position" : 1
  } ]

【问题讨论】:

    标签: elasticsearch


    【解决方案1】:

    我不确定这在技术上是否是最好的,但如果您只是在弹性搜索中获得一个特定答案后,您可以使用带有脚本的过滤器来寻找精确匹配。

    {
      from : 0,
      size : 1,
      "query" : { 
        "text_phrase" : { 
          "title" : "AAPL P JAN 2014 885,00"
        } 
      },
      "filter" : { 
        "script" : { 
          "script" : "_source.exact.contains(x)", 
          "params" : { 
            "x" : "AAPL P JAN 2014 885,00" 
          }  
        } 
      }
    }
    

    我已经使用它从弹性搜索中获取单个已知条目,它对我来说效果很好。

    【讨论】:

      【解决方案2】:

      我想你已经找到答案了,只是想为其他有同样问题的人提供更多信息。

      您使用来自 elasticsearch 文档的 field 查询:

      字段查询:

      针对特定字段执行查询字符串的查询。它是 query_string 查询的简化版本(通过将 default_field 设置为此查询所针对的字段)。

      我相信 query_string 查询是针对文本的,即:它对查询有很大作用,使其变得模糊等等......

      您想要使用(我想您发现了)是一个 term 查询,它不会对搜索短语做任何事情,因此只会给您完全匹配。

      注意:分析发生在 2 个不同的时间,即索引时间和查询时间。设置"analyzer": "keyword" 似乎只影响“使用查询字符串搜索时”form elasticsearch docs 的搜索时间查询。我必须承认我不知道这到底是什么意思(我猜query_string 但它也可能意味着像http://../_search?q=exact:{query here} 这样的搜索)

      【讨论】:

        【解决方案3】:

        您不应该分析您的 id 字段。

        将您的字段定义为:

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

        看看Finding Exact Values

        【讨论】:

          【解决方案4】:

          所有三个文档都得到完全相同的分数,正如您从解释输出中看到的那样,它们都在“AAPL”上匹配。该术语始终在文档中出现一次 (tf=1),并且出现在 37299 个文档中的 211 个 (idf=6.1701355) 中。字段规范要高得多,因为您使用的是索引时间提升(映射中的提升部分,10),反正没什么大不了的,因为匹配总是在同一个字段上。只是如果你在其他领域有比赛,exact 几乎总是会赢,这对你来说可能是有道理的。

          但问题是,如果我查看您的文档,AAPL P JAN 2014 885,00 并不完全匹配。我所看到的是,在您的查询中的 5 个术语中只有一个匹配,您的解释输出中的 coord 也证实了这一点:coord(1/5)`。

          keyword 分析器似乎已应用,但正如您从返回的文档中看到的那样,您并未将 exact 字段的内容作为单个值发送,而是作为值数组发送。由于您使用的是keyword 分析器,因此它的每个项目都不会被标记,但您仍然有多个标记。我想你必须检查你是如何索引文档的。

          【讨论】:

          • 那里有一个完全匹配的,它只是 WAAAAAAAY 下来。
          • 如果你看分数,这对你来说是完全匹配的,而不是弹性搜索/lucene。
          • 我不明白的是:为什么它甚至匹配...我正在使用关键字分析器,它应该将整个字符串作为关键字进行分析...所以我是什么令人惊讶的是,当搜索时,它会将整个事物变成一个令牌,并试图匹配它。但显然这不是正在发生的事情。有什么想法可以让我得到我想要的行为吗?如果一切都匹配,我只想要一个匹配,直到空格。 (最好不区分大小写)
          • 您不是在进行标记,而是将不同的值添加到相同的字段:["APPLE INC","US0378331005","AAPL","73773"]。我认为您必须修复索引部分。
          • 我的用例是我的文档有几个(通常是 4 个)唯一标识它们的值,如果其中一个完全匹配(不区分大小写)我希望该结果在顶部(因此提升 10)如果它不完全匹配,我希望它被忽略。关于如何获得这种行为的任何建议?
          【解决方案5】:

          您的关键字分析器在搜索查询中似乎被忽略的原因是因为 ES 对该字符串进行两次标记 - 首先它运行其 DSL 标记器,然后运行在 rezult 上的映射中指定的标记器。这在这篇文章http://paulsabou.com/blog/2012/03/25/advanced-exact-matching-with-elastic-search/中有更详细的解释

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-08-04
            • 2013-10-13
            • 2020-03-25
            • 2014-08-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多