两个实体:集合和产品。 Collection是产品的母公司。
我需要按产品的条款进行搜索,并展示每个产品有4种产品。
收藏品和产品可以部分匹配,但最先匹配。如果匹配不满,则某些条款具有优先权。
示例:搜索"颜色:红色"和"材料:石头"需要首先显示红色宝石,然后显示任何其他红色(这是关于集合匹配和产品匹配)。
所以,所有这些都是通过以下要求解决的:
{
"query": {
"has_child": {
"type": "products",
"query": {
"bool": {
"should": [
{
"constant_score": {
"filter": {
"match_all": {}
},
"boost": 1
}
},
{
"constant_score": {
"filter": {
"terms": { "_name": "colors", "colors": [5] }
},
"boost": 1.2
}
},
{
"constant_score": {
"filter": {
"terms": { "_name": "materials", "productTypes": [6] }
},
"boost": 1
}
}
]
}
},
"score_mode": "max",
"inner_hits": {
"size": 4,
"sort": [
"_score"
]
}
}
},
"sort": [
"_score"
]
}
好的,现在麻烦了。
需要按价格排序。作为ASC,作为DESC。价格是产品的财产。
需要按匹配产品的价格进行排序,因此无法将价格转移到收藏中。需要按价格排序作为产品的集合。按照匹配产品的最小(或最大)价格排序的集合。
需要按价格排序只有100%匹配的产品(好吧,部分匹配也可以排序,但之后)。我的意思是,排序必须像ORDER BY _score,price
示例,我希望得到,按价格排序asc,[nn]表示部分匹配的产品:
Collection1
100 - 200 - 800 - [99]
Collection2
300 - 500 - [10] - [20]
Collection3
400 - 450 - 500 - [100]
我发现按孩子排序is not supported。并建议重新计算得分。但是我按比赛分数使用得分。 我的尝试是
{
"query": {
"has_child": {
"type": "products",
"query": {
"function_score": {
"query": {
"bool": {
"should": [
... same query as above ...
]
}
},
"functions": [
{
"script_score": {
"script": "ceil(_score * 100) * 100000 + (99999 - doc['price'].value/100)",
"lang": "expression"
}
}
]
}
},
"score_mode": "max",
"inner_hits": {
"size": 4,
"sort": [
"_score",
{
"price": {
"order": "desc"
}
}
]
}
}
},
"sort": [
"_score"
]
}
但我对结果得分感到困惑,我可以在回答中看到。寻求帮助:)或者,可能是,删除它并创建嵌套索引?
UPD:发现分数有问题。默认情况下,弹性组合得分和script_score的结果。因此得分为ceil(_score * 100) * 100000 + (99999 - doc['price'].value/100) * _score
- 这可能会破坏想法,但很容易使用boost_mode
function_score
参数进行修复。结果查询:
{
"query": {
"has_child": {
"type": "products",
"query": {
"function_score": {
"query": {
"bool": {
"should": [
... same query as above ...
]
}
},
"functions": [
{
"script_score": {
"script": "ceil((log10(_score)+10) * 100) * 100000 + (99999 - doc['price'].value)",
"lang": "expression"
}
}
],
"boost_mode": "replace"
}
},
"score_mode": "max",
"inner_hits": {
"size": 4,
"sort": [
"_score",
{
"price": {
"order": "desc"
}
}
]
}
}
},
"sort": [
"_score"
]
}
boost_mode == 'replace
表示"使用功能结果作为得分"。另外,使用log10来确定_score中有多少位数。
按价格排序DESC需要将公式更改为ceil((log10(_score)+10) * 100) * 100000 + (doc['price'].value)
UPD2
公式ceil((log10(_score)+10) * 100) * 100000 + (99999 - doc['price'].value)
返回价格100099952
的{{1}}和价格48
(boost == 1,queryNorm == 1),因为单精度限制。
新公式50
- 减少了得分的位数,并从价格转换为lg价格和减少了位数。欢迎反馈。
答案 0 :(得分:0)
感谢分享,将最新的公式更新为ceil((log10(_score+1)+5) * 100) * 10000 + (9999 - ceil(log10(doc['price'].value +1) * 1000))
,使+1得分,因为在某些情况下它会返回如下错误:
"function score query returned an invalid score: -Infinity for doc: 4580"
更新:出现另一个错误:
"function score query returned an invalid score: NaN for doc: 1739"
将公式更改为ceil((log10(_score+1)+5) * 100) * 10000 + (9999 - ceil(log10(doc['price'].value +1) * 1000))
,为文档值添加了+1,以解决此问题
更新2 :出现另一个错误:
"function score query returned an invalid score: NaN for doc: 1739"
将公式更改为ceil((log10(_score+1)+5) * 100) * 10000 + (9999 - ceil(log10(doc['price'].value > 0 ? doc['price'].value : 1) * 1000))
,将+1替换为表达式