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},
]
}
我想搜索所有带有喜剧和戏剧标签的书籍。
结果顺序是:
- 书 0 (20+30)
- 书 2 (30+5)
- 书 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
对象。这是因为否则所有 t
s 和 w
s 都被扁平化为列表,从而失去过程中的关联(描述为 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"
}
}
}
}
]
}
}
}
我正在使用 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},
]
}
我想搜索所有带有喜剧和戏剧标签的书籍。 结果顺序是:
- 书 0 (20+30)
- 书 2 (30+5)
- 书 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
对象。这是因为否则所有 t
s 和 w
s 都被扁平化为列表,从而失去过程中的关联(描述为 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"
}
}
}
}
]
}
}
}