我确实有产品,并且其中某些产品在特定日期范围内降低了价格。 (简化)示例产品:
{
"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' between specialPrice.fromDate and specialPrice.tillDate) ? specialPrice.value : price
是否可以将其转换为可以在ElasticSearch排序中使用的内容?
进一步说明:默认情况下,所有产品已按几种条件进行排序。用户还可以搜索任何术语并过滤结果,同时还可以选择多个排序参数。例如,可以先按标签对项目进行排序,然后再按价格对项目进行排序,它们都是非常动态的,并且以后仍会按其他一些属性(包括_score)对结果进行排序。 因此,仅更改_score会很不好,因为已经进行了复杂的计算以显示给定搜索词的最佳结果。
这是我当前的脚本,该脚本在第一个params.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',
],
现在我的排序排序脚本确实看起来像这样(在我的测试客户端中,仍在Elastica中实现它):
"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
}
}
}
}
对此我不是100%满意,因为我有冗余的数据和脚本(在脚本中两次调用new Date().getTime()
),但是它确实有效,这是目前最重要的事情:)
答案 0 :(得分:1)
我已经更新了以下查询,请您澄清一下。让我知道是否可行!
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
。
希望有帮助!