Elasticsearch 2.x,查询标记,并按标记weigth排序结果

时间:2016-08-15 11:54:21

标签: elasticsearch elasticsearch-2.0

我正在使用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)
  4. 更新: 我想只返回与两个标签匹配的书籍(并且只按请求的标签排序)。因此,如果我搜索“戏剧”和“喜剧”,则只有具有两个标签的书籍将返回(在本例中为书籍0,书籍1,书籍2),并按要求的标签权重排序。

    我怎么能得到这个?查询的任何例子?

2 个答案:

答案 0 :(得分:3)

Ibrahim's answer如果您总是想要总结所有权重,即使对于与您的查询不匹配的标记,也是正确的。

如果您只想考虑您要搜索的标记权重,则必须将tags编入nested个对象。这是因为否则所有tw都被展平为列表,从而失去了流程中的关联(描述为here)。

然后,您可以使用function_score查询中包含的nested查询来仅汇总匹配标记的权重。您必须启用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的评论===

如果只返回与BOTH标签(示例中的喜剧和戏剧)相匹配的书籍,则会变得有点复杂,因为每个搜索词都需要自己的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"
              }
            }
          }
        }
     ]
    }
  }
}

答案 1 :(得分:1)

试试这个:

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