Elasticsearch查询良好的标题关键字结果

时间:2019-07-16 08:27:33

标签: elasticsearch

我们有一个Elasticsearch索引,其中包含要按标题和描述搜索的产品目录。

我们希望它具有以下约束条件:

  • 我们正在搜索标题和描述,以查找出现的情况(标题中的匹配应该是描述的两倍)
  • 我们希望它具有非常轻的模糊搜索结果(但仍然是准确的结果)
  • 与搜索项不匹配的结果不应被滤除,而只能在以后显示(因此,匹配结果应位于顶部,较差的结果应位于底部)
  • category_id应将产品过滤掉(因此不应显示其他类别的结果)
  • created_at属性在排序时也应被重视。 产品应得分“获得”的“较旧”。 (这非常重要,因为他们每天都在失去重要性)

我试图创建一个类似的查询,但是结果确实不准确。有时会找到完全无关的东西。我认为这是因为通配符查询。

我还认为,对于“ created_at”得分,必须有一个更为优雅的解决方案。对吧?

我正在使用Elasticsearch 6.2

这是我当前的代码。我很高兴看到一个优雅的解决方案:

{
  "sort": [
    {
      "_score": {
        "order": "desc"
      }
    }
  ],
  "min_score": 0.3,
  "size": 12,
  "from": 0,
  "query": {
    "bool": {
      "filter": {
        "terms": {
          "category_id": [
            "212",
            "213"
          ]
        }
      },
      "should": [
        {
          "match": {
            "title_completion": {
              "query": "Development",
              "boost": 20
            }
          }
        },
        {
          "wildcard": {
            "title": {
              "value": "*Development*",
              "boost": 1
            }
          }
        },
        {
          "wildcard": {
            "title_completion": {
              "value": "*Development*",
              "boost": 10
            }
          }
        },
        {
          "match": {
            "title": {
              "query": "Development",
              "operator": "and",
              "fuzziness": 1
            }
          }
        },
        {
          "range": {
            "created_at": {
              "gte": 1563264817998,
              "boost": 11
            }
          }
        },
        {
          "range": {
            "created_at": {
              "gte": 1563264040398,
              "boost": 4
            }
          }
        },
        {
          "range": {
            "created_at": {
              "gte": 1563256264398,
              "boost": 1
            }
          }
        }
      ]
    }
  }
}

1 个答案:

答案 0 :(得分:0)

首先,建立一个返回相关结果的请求通常是一项艰巨的任务。不知道文档的内容就无法完成。就是说,我可以给您一些提示,以满足您的要求,并避免产生不相关的结果。

我们正在搜索标题和描述以查找出现的情况(标题中的匹配应该是描述的两倍)

您可以像在查询中一样使用boost,以使标题匹配与描述相比更加重要。

我们希望它具有非常轻的模糊搜索结果(但仍然是准确的结果)

您应该使用AUTO值作为模糊字段,以根据术语的长度定义不同的模糊度值。例如,默认情况下,少于3个字母的字词(最常见的字词更改会导致不同的字词)将不允许更改。字数超过3个的字词将允许一次更改,超过5个字母的字词将允许2个更改。您可以根据测试更改此行为。

与搜索项不匹配的结果不应被滤除,而只能在以后显示(因此,匹配结果应位于顶部,较差的结果应位于底部)

should语句中使用bool子句。 should语句中的子句不会过滤文档(除非另有说明)。 should子句中的查询仅用于提高得分。

category_id应将产品过滤掉(因此不应显示其他类别的结果)

must语句中使用filter的{​​{1}}子句,以确保所有文档都验证约束。如果您不希望子查询对得分有所帮助(我相信您的情况是这样),请使用bool而不是filter,因为match可以缓存结果。您的查询可以满足此要求。

created_at属性在排序时也应非常高。产品应得分“获得”的“较旧”。 (这非常重要,因为他们每天都在失去重要性)

您应该将function scoredecay function一起使用。如果您还不清楚衰减功能,则可以跳过文档中的方程式,然后跳到可以自我说明的数字。以下查询是使用高斯衰减函数的示例。

filter

编写查询的提示

  • 避免通配符查询:如果您使用{ "function_score": { // Name of the decay function "gauss": { // Field to use "created_at": { "origin": "now", // "now" is the default so you can omit this field "offset": "1d", // Values with less than 1 day will not be impacted "scale": "10d", // Duration for which the scores will be scaled using a gauss function "decay" : 0.01 // Score for values further than scale } } } } ,则效率不高,并且会占用大量内存。如果您希望能够部分搜索词(当用户搜索“ house”时找到“ penthouse”),则应使用ngram tokenizer创建一个子字段,并使用该子字段编写标准的*查询

  • 避免设置最低分数:分数是相对值。低分或高分并不表示该文件是否相关。您可以阅读this article关于该主题的信息。

  • 请谨慎处理match个查询:模糊会产生很大的噪音并使用户感到困惑。通常,我建议增加默认的fuzzy模糊阈值,并接受某些拼写错误的查询不会返回好的结果。通常,与理解为什么他得到完全不相关的结果相比,用户检测到输入中的拼写错误更容易。

查询示例

这只是您需要适应数据的一个示例。

AUTO
相关问题