【问题标题】:Elasticsearch - filter and sort by name with Priority exceptionsElasticsearch - 按名称过滤和排序,优先级例外
【发布时间】:2017-07-27 20:41:08
【问题描述】:

我正在尝试使用优先级例外按名称进行过滤和排序,这意味着即使结果按字母顺序排序,我也希望特定名称首先出现。

例如 - 这是我的基本查询

{
  "from": 0,
  "size": 500,
  "min_score": 0.15,
  "query": {
    "filtered": {
      "filter": {
        "bool": {
          "must": [
            {
              "exists": {
                "field": "brand.id"
              }
            }
          ]
        }
      }
    }
  },
  "sort": [
    {
      "brand.names.1.raw": "asc"
    }
  ]
}

简而言之,我希望这个数组 ["pepsi" , "rc-cola", "coca-cola"] 通过将 top priority 赋予 "rc-cola" 进行排序,以便它将被排序为 ["rc-cola", "coca-cola", "pepsi"]

现在它按字母顺序排序。 我想到了一些可行的想法:

  1. 添加一个“应该”并通过“匹配”进行提升。但后来我遇到了问题 按“_score”排序,它打破了我按字母顺序排序,尽管我首先按“_score”和品牌名称排序。将其添加到“bool”的示例:“should”:[{“match”:{“brand.id”:{“query”:34709,“boost”:20}}}

  2. 我尝试使用“聚合”,以便第一个查询(存储桶)是 “匹配”特定品牌名称并按字母顺序在里面排序, 第二个查询将仅按字母顺序排序。但我完全搞砸了。

我必须使用过滤 -> 过滤器,我不能使用脚本查询。 谢谢。

更新 这是一个文档示例以及它现在是如何排序的。 我希望优先考虑“ccc”品牌,请帮我更新我的查询。

{
  "_index": "retailer1",
  "_type": "product",
  "_id": "1",
  "_score": null,
  "_source": {
    "id": 1,
    "brand": {
      "names": {
        "1": "aaa"
      },
      "id": 405
    }
  },
  "sort": [
    "aaa"
  ]
},
{
  "_index": "retailer1",
  "_type": "product",
  "_id": "2",
  "_score": null,
  "_source": {
    "id": 2,
    "brand": {
      "names": {
        "1": "bbb"
      },
      "id": 406
    }
  },
  "sort": [
    "bbb"
  ]
},
{
  "_index": "retailer1",
  "_type": "product",
  "_id": "3",
  "_score": null,
  "_source": {
    "id": 3,
    "brand": {
      "names": {
        "1": "ccc"
      },
      "id": 407
    }
  },
  "sort": [
    "ccc"
  ]
},

【问题讨论】:

  • 以下。我也尝试在没有脚本的情况下做同样的事情。
  • 那个数组是什么?您希望品牌按您的优先级排序还是什么?
  • 如果您发布文档示例和预期结果将有助于理解
  • @VolodymyrBilyachat - 帖子更新
  • 能否指出您使用的 Elasticsearch 版本?我相信这与可用的选项有关。

标签: javascript node.js sorting elasticsearch indexing


【解决方案1】:

如果使用 Elasticsearch 1.x 版,以下查询应该会为您提供预期的结果: (如果需要,可能需要稍作调整才能使用原始字段)

{
  "from": 0,
  "size": 500,
  "query": {
    "filtered": {
      "query": {
        "bool": {
          "should": [
            {
              "term": {
                "brand.names.1": "ccc",
                "boost": 10
              }
            },
            {
              "exists": {
                "field": "brand.id"
              }
            }
          ]
        }
      },
      "filter": {
        "exists": {
          "field": "brand.id"
        }
      }
    }
  },
  "sort": [
    "_score",
    {
      "brand.names.1": {
        "order": "asc"
      }
    }
  ]
}

在更高版本的 Elasticsearch The filtered query is replaced by the bool query 上, 这个查询应该可以完成这项工作(如果需要,可以使用与前一个类似的调整来使用原始字段)

{
  "from": 0,
  "size": 500,
  "query": {
    "bool": {
      "filter": {
        "exists": {
          "field": "brand.id"
        }
      },
      "should": [
        {
          "term": {
            "brand.names.1": "ccc"
          }
        }
      ]
    }
  },
  "sort": [
    "_score",
    {
      "brand.names.1": {
        "order": "asc"
      }
    }
  ]
}

在这两种情况下,如果您希望顶部以给定的顺序填充多个首选匹配项,则可以使用 boost 函数

【讨论】:

    【解决方案2】:

    如果品牌的优先级在索引时是已知的,那么你可以直接在你的文档中索引它:

    "brand": {
          "name": "ccc",
          "priority":1000,
          "id": 407
        }
    

    要显示在顶部的品牌可以具有较高的人气值,而其余品牌的人气值可能被分配到较低的值。

    通过这种方式索引,可以直接将brand.popularity作为一级排序,brand.names作为二级排序

    "sort" : [
            { "brand.priority" : {"order" : "desc"}},
            { "brand.name" : {"order" : "asc" }}
        ]
    

    【讨论】:

    • 谢谢,但我不想依赖索引
    • 你的意思是任何品牌对于不同的查询可以有不同的优先级?
    • 不,我知道我可以在索引中做到这一点,我不想让它依赖于索引。我有一些商业原因。我正在寻找其他选择。谢谢
    • 在查询时,您将如何传递品牌的相对优先级,因为可能不知道哪些品牌将与您的过滤条件匹配。整体品牌列表也可能会大幅增长。
    • 这正是我的要求,我想提升具有优先级的品牌,并确保其他品牌仍将按字母顺序排序
    【解决方案3】:

    我已经在这里测试了本地化。另外为了简化查询,不要询问名称,而是询问品牌 ID,因为您的品牌可能有很多名称。如果您仍然希望对名称进行排序,那么您可以根据需要修改脚本

    POST stack/_search
    {
      "query": {
        "function_score": {
          "boost_mode": "replace",
          "query": {
            "bool": {
              "must": [
                {
                  "exists": {
                    "field": "brand.id"
                  }
                }
              ]
            }
          },
          "script_score": {
            "script": {
              "params": {
                "ids": [
                  406,
                  405
                ]
              },
              "inline": "return params.ids.indexOf(doc['brand.id'].value) > -1 ? 1000 - params.ids.indexOf(doc['brand.id'].value) : _score;"
            }
          }
        }
      }
    }
    

    【讨论】:

    • 谢谢,但正如我所说:“我必须使用过滤 -> 过滤器,我不能使用脚本查询。”
    猜你喜欢
    • 1970-01-01
    • 2018-05-15
    • 1970-01-01
    • 1970-01-01
    • 2019-04-15
    • 1970-01-01
    • 2020-06-23
    • 1970-01-01
    • 2015-03-07
    相关资源
    最近更新 更多