B2B平台涉及到根据不同的会员进行排序,存在Elasticsearch的数据结构大概是这样:
"id":1,
"price":200,
"unitPriceStrategyList" : [
{
"id" : 27,
"memberPrice" : 500.0,
"commodityMemberList" : [
{
"memberId" : 157,
"memberRoleId" : 8
},
{
"memberId" : 300,
"memberRoleId" : 4
}
],
"isEnable" : true
},
{
"id" : 28,
"memberPrice" : 100.0,
"commodityMemberList" : [
{
"memberId" : 152,
"memberRoleId" : 8
},
{
"memberId" : 298,
"memberRoleId" : 4
}
],
"isEnable" : true
}
]
根据当前登录人,比如是:memberId=157,memberRoleId=8的人进来,就看到500,如果是memberId=152,memberRoleId=8的人进来,就看到100,其他人不在unitPriceStrategyList.commodityMemberList里面的就看到外面的price价格,也就是200,然后根据看到的价格进行升序和降序排序
用script方式是可以实现这个需求,但是性能太差了,在生产环境压根就不能用
通过Elasticsearch本身的聚合或者重打分实现上面的需求
该回答引用GPTᴼᴾᴱᴺᴬᴵ
根据您的需求,您可以考虑使用Elasticsearch中的nested数据类型来存储unitPriceStrategyList中的嵌套结构,以便查询时能够准确匹配。建议将unitPriceStrategyList中的数据展开,每一条数据表示一种商品价格策略,以方便查询。例如,将数据转换成以下格式:
"id":1,
"price":200,
"unitPriceStrategyList" : [
{
"id" : 27,
"memberId" : 157,
"memberRoleId" : 8,
"memberPrice" : 500.0,
"isEnable" : true
},
{
"id" : 27,
"memberId" : 300,
"memberRoleId" : 4,
"memberPrice" : 500.0,
"isEnable" : true
},
{
"id" : 28,
"memberId" : 152,
"memberRoleId" : 8,
"memberPrice" : 100.0,
"isEnable" : true
},
{
"id" : 28,
"memberId" : 298,
"memberRoleId" : 4,
"memberPrice" : 100.0,
"isEnable" : true
}
]
接下来,您可以使用nested数据类型来定义unitPriceStrategyList的mapping,如下所示:
PUT /my_index
{
"mappings": {
"properties": {
"id": {
"type": "integer"
},
"price": {
"type": "double"
},
"unitPriceStrategyList": {
"type": "nested",
"properties": {
"id": {
"type": "integer"
},
"memberId": {
"type": "integer"
},
"memberRoleId": {
"type": "integer"
},
"memberPrice": {
"type": "double"
},
"isEnable": {
"type": "boolean"
}
}
}
}
}
}
接下来,您可以使用nested查询来查询符合条件的数据,并使用nested_path参数来指定unitPriceStrategyList的路径。例如,查询memberId=157和memberRoleId=8的数据,可以使用以下查询:
GET /my_index/_search
{
"query": {
"nested": {
"path": "unitPriceStrategyList",
"query": {
"bool": {
"must": [
{
"term": {
"unitPriceStrategyList.memberId": 157
}
},
{
"term": {
"unitPriceStrategyList.memberRoleId": 8
}
}
]
}
}
}
}
}
接下来,您可以使用Elasticsearch的排序功能来对查询结果进行排序。例如,使用以下查询对数据按照memberPrice进行升序排序:
GET index_name/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"unitPriceStrategyList.commodityMemberList.memberId": {
"value": 157
}
}
},
{
"term": {
"unitPriceStrategyList.commodityMemberList.memberRoleId": {
"value": 8
}
}
}
]
}
},
"sort": [
{
"unitPriceStrategyList.memberPrice": {
"order": "asc"
}
}
]
}
这个查询使用bool查询来限制memberId和memberRoleId,然后使用sort来按照unitPriceStrategyList.memberPrice进行升序排序。如果需要降序排序,只需要将"order"的值从"asc"改为"desc"即可。
参考GPT和自己的思路,可以使用Elasticsearch的function_score查询来实现这个需求,function_score查询可以通过将文档的_score与用户定义的函数结果相结合来重新计算文档的_score,从而影响排序。在这个需求中,我们可以使用function_score查询来重新计算文档的_score,以根据用户的角色和价格选择适当的价格进行排序。
以下是一个可能的查询示例,它使用function_score查询和nested聚合来实现上述需求:
{
"query": {
"function_score": {
"query": {
"match_all": {}
},
"functions": [
{
"filter": {
"nested": {
"path": "unitPriceStrategyList",
"query": {
"bool": {
"must": [
{
"term": {
"unitPriceStrategyList.isEnable": true
}
},
{
"nested": {
"path": "unitPriceStrategyList.commodityMemberList",
"query": {
"bool": {
"must": [
{
"term": {
"unitPriceStrategyList.commodityMemberList.memberId": 157
}
},
{
"term": {
"unitPriceStrategyList.commodityMemberList.memberRoleId": 8
}
}
]
}
}
}
}
]
}
}
}
},
"weight": 2
},
{
"filter": {
"nested": {
"path": "unitPriceStrategyList",
"query": {
"bool": {
"must": [
{
"term": {
"unitPriceStrategyList.isEnable": true
}
},
{
"nested": {
"path": "unitPriceStrategyList.commodityMemberList",
"query": {
"bool": {
"must": [
{
"term": {
"unitPriceStrategyList.commodityMemberList.memberId": 152
}
},
{
"term": {
"unitPriceStrategyList.commodityMemberList.memberRoleId": 8
}
}
]
}
}
}
}
]
}
}
}
},
"weight": 1
}
],
"score_mode": "sum",
"boost_mode": "multiply"
}
},
"sort": [
{
"_score": {
"order": "desc"
}
},
{
"price": {
"order": "asc"
}
}
],
"aggs": {
"prices": {
"nested": {
"path": "unitPriceStrategyList"
},
"aggs": {
"price": {
"min": {
"script": "doc['price'].value"
}
}
}
}
}
}
该查询包括以下组件:
一个function_score查询,其中包括两个函数。第一个函数使用nested查询和bool查询来匹配适当的价格,并使用较高的权重来增加该价格的影响力。第二个函数使用相同的查询来匹配次佳价格,并使用较低的权重增加其影响力。两个函数的结果将相乘以影响排序顺序。
一个排序,首先按照匹配的价格降序排序,然后按照价格是否匹配以及价格值升序排序。这将使匹配的价格始终排在非匹配价格的前面,并按照价格值升序排序。
下面是一个可能的Elasticsearch查询示例,假设当前登录用户的memberId为157,memberRoleId为8:
{
"query": {
"function_score": {
"query": {
"bool": {
"should": [
{
"nested": {
"path": "unitPriceStrategyList",
"score_mode": "sum",
"query": {
"bool": {
"must": [
{
"range": {
"unitPriceStrategyList.memberPrice": {
"lte": 10000
}
}
},
{
"nested": {
"path": "unitPriceStrategyList.commodityMemberList",
"query": {
"bool": {
"must": [
{
"terms": {
"unitPriceStrategyList.commodityMemberList.memberId": [
157
]
}
},
{
"terms": {
"unitPriceStrategyList.commodityMemberList.memberRoleId": [
8
]
}
}
]
}
}
}
}
]
}
},
"boost_factor": 2
}
},
{
"nested": {
"path": "unitPriceStrategyList",
"score_mode": "sum",
"query": {
"bool": {
"must": [
{
"range": {
"unitPriceStrategyList.memberPrice": {
"lte": 10000
}
}
},
{
"nested": {
"path": "unitPriceStrategyList.commodityMemberList",
"query": {
"bool": {
"must": [
{
"terms": {
"unitPriceStrategyList.commodityMemberList.memberId": [
152
]
}
},
{
"terms": {
"unitPriceStrategyList.commodityMemberList.memberRoleId": [
8
]
}
}
]
}
}
}
}
]
}
},
"boost_factor": 0.5
}
}
]
}
},
"functions": [
{
"field_value_factor": {
"field": "unitPriceStrategyList.memberPrice",
"modifier": "log1p",
"factor": 2
}
}
],
"score_mode": "multiply"
}
},
"sort": [
{
"_score": {
"order": "desc"
}
},
{
"price": {
"order": "asc"
}
}
]
}
在这个查询中,我们添加了一个嵌套查询,用于匹配次佳价格。我们使用相同的嵌套路径和布尔查询来匹配 memberRoleId=8 和 memberId=152 的价格。我们使用了一个较低的 boost_factor 来减小次佳价格的影响力。
最后,我们将两个函数的结果相乘以影响排序顺序,然后使用 _score 和价格字段进行排序。
希望这可以帮助你解决你的问题!
以下答案由GPT-3.5大模型与博主波罗歌共同编写:
可以通过Elasticsearch中的function_score query来实现这个需求,具体的步骤如下:
使用bool query把不在unitPriceStrategyList.commodityMemberList里面的文档和在里面但是会员价格为null的文档过滤掉。
使用function_score query对剩下的文档进行重打分操作。
在重打分操作中,使用script_score进行自定义脚本计算,根据当前登录人的memberId和memberRoleId计算出当前会员价格。
然后使用field_value_factor将计算出来的会员价格作为因子进行计算,达到根据会员价格进行排序的目的。
具体实现代码如下:
POST index/_search
{
"query": {
"bool": {
"filter": [
{
"bool": {
"should": [
{
"nested": {
"path": "unitPriceStrategyList",
"query": {
"bool": {
"must": [
{
"term": {
"unitPriceStrategyList.commodityMemberList.memberId": 157
}
},
{
"term": {
"unitPriceStrategyList.commodityMemberList.memberRoleId": 8
}
}
]
}
}
}
},
{
"bool": {
"must_not": [
{
"nested": {
"path": "unitPriceStrategyList",
"query": {
"bool": {
"must": [
{
"exists": {
"field": "unitPriceStrategyList.commodityMemberList.memberRoleId"
}
},
{
"term": {
"unitPriceStrategyList.commodityMemberList.memberId": 157
}
}
]
}
}
}
}
]
}
}
]
}
}
]
}
},
"sort": [
{
"_score": {
"order": "desc"
}
},
{
"price": {
"order": "desc"
}
}
],
"size": 10,
"from": 0,
"track_total_hits": true,
"explain": true,
"min_score": 0
"rescore": {
"window_size": 1000,
"query": {
"rescore_query": {
"function_score": {
"query": {"match_all": {}},
"script_score": {
"script": {
"source": """
def price = 0;
boolean flag = false;
for (def i = 0; i < doc['unitPriceStrategyList.commodityMemberList.memberId'].length; i++) {
if (doc['unitPriceStrategyList.commodityMemberList.memberId'][i].value == params.memberId &&
doc['unitPriceStrategyList.commodityMemberList.memberRoleId'][i].value == params.memberRoleId
) {
if (doc['unitPriceStrategyList.memberPrice'].length > i && doc['unitPriceStrategyList.memberPrice'][i].value != null) {
price = doc['unitPriceStrategyList.memberPrice'][i].value;
flag = true;
break;
}
}
}
if (flag) {
return price;
} else {
return doc['price'].value;
}
""",
"params": {
"memberId": 157,
"memberRoleId": 8
}
}
},
"field_value_factor": {
"field": "memberPrice",
"factor": 1,
"modifier": "log1p",
"missing": 0
},
"boost_mode": "multiply"
}
}
}
}
}
这里使用了嵌套查询(nested query)来查询unitPriceStrategyList中的文档,然后使用function_score query来进行重打分操作,其中包含自定义脚本计算和field_value_factor计算因子。最后在sort中根据_score和price进行排序。
如果我的回答解决了您的问题,请采纳!
该回答引用ChatGPT
您可以使用Elasticsearch中的Function Score Query实现根据不同的会员进行排序。该查询可以通过定义一个或多个函数,以一种灵活的方式修改文档的分数,从而影响搜索结果的排序。
在这种情况下,您可以使用Script Score Function和Field Value Factor Function两个函数来实现您的需求。Script Score Function将通过比较当前登录人的ID和角色ID与unitPriceStrategyList中的commodityMemberList中的成员ID和角色ID来计算文档的得分。Field Value Factor Function将使用文档中的价格作为因子来调整得分。
以下是使用Function Score Query的示例查询:
{
"query": {
"function_score": {
"query": {
"match_all": {}
},
"functions": [
{
"script_score": {
"script": {
"source": """
def member_id = params.member_id;
def member_role_id = params.member_role_id;
def unit_price_strategy_list = doc['unitPriceStrategyList'];
def max_price = doc['price'].value;
for (def i = 0; i < unit_price_strategy_list.length; i++) {
def strategy = unit_price_strategy_list[i];
for (def j = 0; j < strategy['commodityMemberList'].length; j++) {
def member = strategy['commodityMemberList'][j];
if (member['memberId'] == member_id && member['memberRoleId'] == member_role_id) {
return strategy['memberPrice'];
}
}
if (strategy['isEnable'] && strategy['memberPrice'] > max_price) {
max_price = strategy['memberPrice'];
}
}
return max_price;
""",
"params": {
"member_id": 157,
"member_role_id": 8
}
}
}
},
{
"field_value_factor": {
"field": "price",
"modifier": "log1p",
"factor": 0.1
}
}
],
"boost_mode": "multiply"
}
}
}
在这个查询中,我们使用了两个函数:Script Score Function和Field Value Factor Function。Script Score Function首先查找unitPriceStrategyList中与当前登录用户匹配的成员,并返回该成员的价格。如果没有匹配的成员,则返回最高价格。Field Value Factor Function将价格作为因子应用于得分,并使用log1p修改因子的影响,以避免价格因子对得分的影响过大。
请注意,此查询只是示例代码,并未经过测试和优化,因此可能需要根据您的具体需求进行调整和修改。