两个实体:集合和产品.收集是产品的父母.
我需要按照产品的条款进行搜索,并展示每个产品有4个产品.
收藏品和产品可以部分匹配,但最先匹配.如果匹配不满,则某些条款具有优先权.
示例:搜索"color:red"和"material:stone"需要首先显示红色宝石,然后显示任何其他红色(这是关于集合匹配和产品匹配).
所以,所有这些都通过以下要求解决:
{
"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"
]
}
Run Code Online (Sandbox Code Playgroud)
好的,现在麻烦了.
需要按价格排序.作为ASC,作为DESC.价格是产品的财产.
需要按匹配产品的价格排序,因此无法将价格转移到收集.需要按价格排序作为产品的集合.按照匹配产品的最小(或最大)价格排序的集合.
需要按价格排序只有100%匹配的产品(嗯,部分匹配也可以排序,但之后).我的意思是,排序必须像ORDER BY _score,price
例如,我想得到的,按价格排序asc,[nn]表示部分匹配的产品:
Collection1
100 - 200 - 800 - [99]
Collection2
300 - 500 - [10] - [20]
Collection3
400 - 450 - 500 - [100]
Run Code Online (Sandbox Code Playgroud)
我发现不支持按孩子排序.并建议重新计算得分.但我正在使用得分排序.我的尝试是
{
"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"
]
}
Run Code Online (Sandbox Code Playgroud)
但我真的对结果得分感到困惑,我可以在回答中看到.请求帮助:)或者,可能是,删除它并创建嵌套索引?
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"
]
}
Run Code Online (Sandbox Code Playgroud)
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价格48和价格50(boost == 1,queryNorm == 1).
新公式ceil((log10(_score)+5) * 100) * 10000 + (9999 - ceil(log10(doc['price'].value) * 1000))- 减少了得分的位数,并从价格转换为lg价格和减少的位数.欢迎反馈.
感谢分享,更新了最新公式以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"
Run Code Online (Sandbox Code Playgroud)
更新:出现另一个错误:
"function score query returned an invalid score: NaN for doc: 1739"
Run Code Online (Sandbox Code Playgroud)
更改公式以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"
Run Code Online (Sandbox Code Playgroud)
更改公式以ceil((log10(_score+1)+5) * 100) * 10000 + (9999 - ceil(log10(doc['price'].value > 0 ? doc['price'].value : 1) * 1000))用表达式替换 +1
更新 3:出现另一个错误:
不再有错误消息,现在很难找到,但它与之前的类似:(
将公式更改为ceil(_score+1) + ceil((doc['price'].value > 0 ? doc['price'].value : 1) * 100)简化公式,这样我就可以理解并且它今天仍然有效:)
| 归档时间: |
|
| 查看次数: |
1509 次 |
| 最近记录: |