Elasticsearch [=10th=],查询标签,按标签权重排序结果

Elasticsearch 2.x, query for tag, and sort results by tag weigth

我正在使用 elasticsearch 2.3

我有一个书籍索引。每本书都有标签,每个标签都有重量。 我想获取所有具有请求标签的书籍,按标签重量排序。

例如:

PUT book/book/0
{
    "name": "book 0",
    "tags": [
        {"t": "comedy", "w": 30},
        {"t": "drama","w": 20},
    ]
}

PUT book/book/1
{
    "name": "book 1",
    "tags": [
        {"t": "comedy", "w": 10},
        {"t": "drama","w": 5},
        {"t": "other","w": 50},
    ]
}

PUT book/book/2
    {
        "name": "book 2",
        "tags": [
            {"t": "comedy", "w": 5},
            {"t": "drama","w": 30},
        ]
    }

PUT book/book/3
    {
        "name": "book 3",
        "tags": [
            {"t": "comedy", "w": 5},
            {"t": "other","w": 30},
        ]
    }

我想搜索所有带有喜剧和戏剧标签的书籍。 结果顺序是:

  1. 书 0 (20+30)
  2. 书 2 (30+5)
  3. 书 1 (10+5)

更新: 我只想 return 只匹配两个标签的书(并且只按请求的标签排序)。因此,如果我搜索 'drama' 和 'comedy',只有同时具有两个标签的书才会 return(在本例中为书 0、书 1、书 2),按请求的标签权重排序。

我怎样才能得到这个?有查询的例子吗?

试试这个:

POST book/book/_search
{
    "query": {
        "match": {
           "tags.t": "comedy drama"
        }
    },
    "sort": [
       {
          "tags.w": {
             "order": "desc",
             "mode": "sum"
          }
       }
    ]
}

如果您总是想对所有权重求和,即使对于与您的查询不匹配的标签也是如此。

如果您只想考虑要搜索的标签的权重,则必须将 tags 索引为 nested 对象。这是因为否则所有 ts 和 ws 都被扁平化为列表,从而失去过程中的关联(描述为 here)。

然后您可以使用包裹在 nested 查询中的 function_score 查询来仅汇总匹配标签的权重。您将必须启用 scripting.

这是一个例子:

GET /book/_search
{
  "query": {
    "nested": {
      "path": "tags",
      "query": {
        "function_score": {
          "query": {
            "bool": {
              "filter": [
                {
                  "terms": {
                    "tags.t": [
                      "comedy",
                      "drama"
                    ]
                  }
                }
              ]
            }
          },
          "functions": [
            {
              "script_score": {
                "script": "return doc['tags.w'].value"
              }
            }
          ],
          "boost_mode": "replace"
        }
      },
      "score_mode": "sum"
    }
  }
}


=== 编辑@Eyal Ch 的评论 ===

如果只返回匹配两个标签(示例中的喜剧和戏剧)的书籍,它会变得有点复杂,因为每个搜索词都需要自己的 nested 查询。

这是一个例子:

GET /book/_search
{
  "query": {
    "bool": {
      "must":
      [
        {
          "nested": {
            "path": "tags",
            "query": {
              "function_score": {
                "query": {
                  "term": {
                    "tags.t": {
                      "value": "comedy"
                    }
                  }
                },
                "functions": [
                  {
                    "script_score": {
                      "script": "return doc['tags.w'].value"
                    }
                  }
                ],
                "boost_mode": "replace"
              }
            }
          }
        },
        {
          "nested": {
            "path": "tags",
            "query": {
              "function_score": {
                "query": {
                  "term": {
                    "tags.t": {
                      "value": "drama"
                    }
                  }
                },
                "functions": [
                  {
                    "script_score": {
                      "script": "return doc['tags.w'].value"
                    }
                  }
                ],
                "boost_mode": "replace"
              }
            }
          }
        }
     ]
    }
  }
}