Sorting 条件ElasticSearch按不同字段排序(如果在范围内)
我确实有产品,其中一些在特定日期范围内降价。 (简化)示例产品:Sorting 条件ElasticSearch按不同字段排序(如果在范围内),sorting,
elasticsearch,Sorting,
elasticsearch,我确实有产品,其中一些在特定日期范围内降价。 (简化)示例产品: { "id": 1, "price": 2.0, "specialPrice": { "fromDate": null, "tillDate": null, "value": 0, }, }, { "id": 2, "price": 4.0, "specialPrice": { "fromDate": 1540332000, "tillDate": 1571781
{
"id": 1,
"price": 2.0,
"specialPrice": {
"fromDate": null,
"tillDate": null,
"value": 0,
},
},
{
"id": 2,
"price": 4.0,
"specialPrice": {
"fromDate": 1540332000,
"tillDate": 1571781600,
"value": 2.5,
},
},
{
"id": 3,
"price": 3.0,
"specialPrice": {
"fromDate": null,
"tillDate": null,
"value": 0,
},
}
按价格过滤没有问题。我可以用一个简单的布尔查询
但是我还没有找到一个ElasticSearch脚本的好例子,它可以为我指明正确的方向,即使它应该非常简单,因为你知道语法
我的伪代码:price=('now'介于specialPrice.fromDate和specialPrice.tillDate之间)?specialPrice.value:价格
有没有一种方法可以将其转换为在ElasticSearch排序中工作的内容
进一步澄清:默认情况下,所有产品都已按多个条件排序。用户还可以搜索任何术语并过滤结果,同时还可以选择多个排序参数。例如,项目可以按标签排序,然后按价格排序,这都是非常动态的,之后它仍然会按一些其他属性(包括_分数)对结果进行排序。
因此,仅仅改变_分数是不好的,因为这已经是在一个复杂的问题中计算出来的,以显示给定搜索词的最佳结果
这是我当前的脚本,它在第一个参数时失败。currentDate
:
"sort": {
"_script": {
"type": "number",
"script": {
"source": "if(doc['specialPrice.tillDate'] > params.currentDate) {params.currentPrice = doc['specialPrice.value']} return params.currentPrice",
"params": {
"currentDate": "now",
"currentPrice": "doc['price']"
}
}
}
它现在是如何工作的: 一个问题是一些属性的嵌套。 因此,我的一个步骤是将它们的内容复制到产品的新字段中(我对此不太满意,但不管怎样)。 因此,在我的映射中,我为产品创建了新属性(specialFrom、specialTill、specialValue),并在specialPrice“copy_to”属性中使用新的属性名称给出了相应的字段。 该部分采用php数组语法,因为我使用的是ruflin/elastica:
'specialPrice' => [
'type' => 'nested',
'properties' => [
'fromDate' => [
'type' => 'date',
'format' => 'epoch_second',
'copy_to' => 'specialFrom',
],
'tillDate' => [
'type' => 'date',
'format' => 'epoch_second',
'copy_to' => 'specialTill',
],
'value' => [
'type' => 'float',
'copy_to' => 'specialValue',
],
],
],
'specialFrom' => [
'type' => 'date',
'format' => 'epoch_second',
],
'specialTill' => [
'type' => 'date',
'format' => 'epoch_second',
],
'specialValue' => [
'type' => 'float',
],
"sort": {
"_script": {
"type": "number",
"script": {
"lang": "painless",
"source": "params.param = ((doc['specialTill'].value - new Date().getTime()) > 0 && (new Date().getTime() - doc['specialFrom'].value) > 0) ? doc['specialValue'].value : doc['price'].value; return params.param;",
"params": {
"param": 0.0
}
}
}
现在,我的排序脚本看起来确实是这样的(在我的测试客户机中,仍在致力于在elastica中实现它):
}
我对此不是100%满意,因为我有多余的数据和脚本(在脚本中调用两次
new Date().getTime()
),但它确实有效,这是目前最重要的:)我已经更新了下面的查询,发布了您的澄清。让我知道这是否有效
POST dateindex/_search
{
"query":{
"match_all":{ // you can ignore this, I used this to test at my end
}
},
"sort":{
"_script":{
"type":"number",
"script":{
"lang":"painless",
"inline":" params.param = ((doc['specialPrice.tillDate'].value - new Date().getTime()) > 0) ? doc['specialPrice.value'].value : doc['price'].value; return params.param;",
"params":{
"param":0.0
}
},
"order":"asc"
}
}
}
您可以尝试在上面的查询中使用source
而不是inline
,因为我一直在我的机器上测试ES5.X
版本
希望有帮助 谢谢,但我不确定这是否真的对我有帮助。我本以为会发生这样的事情:从我对你答案的理解来看,每次我想按价格排序时,我都必须更新我所有产品的价格。这对我来说似乎不是很有效;)我会继续试验的。@FanMake只是想说清楚,你不想更新价格。只需要排序,它应该按照您提供的psuedo代码工作?这是正确的。如果用户选择按价格排序,ElasticSearch应使用“特价”,如果它在当前日期有效,则使用正常价格,否则:)@Fanmake请立即检查我的答案。我已经更新了另一个解决方案。如果有帮助,请告诉我!非常感谢您的帮助和耐心!:D根据你更新的脚本,我最终设法使它与我的数据一起工作,并相应地更新了我的答案。