ES实现“小于XX时间”排前面(或后面)“大于XX时间”排后面(或前面)排序

简介: ES实现“小于XX时间”排前面(或后面)“大于XX时间”排后面(或前面)排序

1、问题描述

一位学生问我一个问题,实现es查询:对于查询的结果要分成两类【过期和没过期,按照过期时间判断】。没过期的排在前面,过期的排在后面。最后,不管是过期的还是没过期的,在组内都再按照标定时间字段进行倒排序。


是否过期通过过期时间字段进行判断。

aef3543c69f646dc930fe8744e86d849.png


2、误区

对于此类需求,要对一个不存在的字段进行操作,第一应该想到的就是script_fields

一开始思路是这样的,伪代码如下:

GET <index>/_search
{
  "script_fields": {
    "是否逾期": {
      "script": {
          "lang": "painless",
          "source": """
              if(逾期=true) {
                return 1;
              }else{
                return 0;
              }
          """
      }
    }
  }, 
  "sort": [
    {
      "是否逾期": {
        "order": "desc"
      }
    },
    {
      "标定时间":{
        "order": "desc"
      }
    }
  ]
}


3、解决方案

上面方案后发现排序在外部无法对script_field进行调用。于是对script做出修改,把脚本查询写在sort内部。基于product索引模拟的案例如下:


这里假设product索引中 价格> 3000 的类比上述案例中逾期,小于等于 3000 的类比上述案例中未逾期,然后按照价格(类比于标定日期)进行排序(product索引数据在文末体现)


代码如下:

# 先根据价格级别(不存在字段)排序,大于3000的排上面,小于等于3000的排下面
# 其次按照价格倒叙排序
GET product/_search
{
  "sort": [
    {
      "_script": {
        "script": {
          "lang": "painless",
          "source": """
              if(params['_source']['price']>3000) {
                return 1;
              }else{
                return 0;
              }
            """
        },
        "type": "number",
        "order": "desc"
      }
    },
    {
      "price": {
        "order": "desc"
      }
    }
  ]
}


4、附:Product索引数据

```json
PUT /product/_doc/1
{
    "name" : "xiaomi phone",
    "desc" :  "shouji zhong de zhandouji",
    "price" :  3999,
    "lv":"qijianji",
    "type":"phone",
    "createtime":"2020-10-01T08:00:00Z",
    "tags": [ "xingjiabi", "fashao","buka" ]
}
PUT /product/_doc/2
{
    "name" : "xiaomi nfc phone",
    "desc" :  "zhichi quangongneng nfc,shouji zhong de jianjiji",
    "price" :  4999,
    "lv":"qijianji",
    "type":"phone",
    "createtime":"2020-05-21T08:00:00Z",
    "tags": [ "xingjiabi", "fashao","gongjiaoka" ]
}
PUT /product/_doc/3
{
    "name" : "nfc phone",
    "desc" :  "shouji zhong de hongzhaji ",
    "price" :  2999,
    "lv":"gaoduanji",
    "type":"phone",
    "createtime":"2020-06-20",
    "tags": [ "xingjiabi", "fashao", "menjinka" ]
}
PUT /product/_doc/4
{
    "name" : "xiaomi erji",
    "desc" :  "erji zhong de huangmenji",
    "price" :  999,
    "lv":"baiyuanji",
    "type":"erji",
    "createtime":"2020-06-23",
    "tags": [ "low", "bufangshui","yinzhicha" ]
}
PUT /product/_doc/5
{
    "name" : "hongmi erji",
    "desc" :  "erji zhong de kendeji nfc",
    "price" :  399,
    "type":"erji",
    "lv":"baiyuanji",
    "createtime":"2020-07-20",
    "tags": [ "lowbee","xuhangduan", "zhiliangx" ]
}
PUT /product/_doc/6
{
    "name" : "xiaomi phone 10",
    "desc" :  "chongdian zeikuai diaodian gengkuai,chaoji wudi wangyuanjing,gaoshua dianjingping",
    "price" :  "5999",
    "lv":"qijianji",
    "type":"phone",
    "createtime":"2020-07-27",
    "tags": [ "120Hz", "120W", "120bianjiao" ]
}
PUT /product/_doc/7
{
    "name" : "aipao SE2",
    "desc" :  "chule CPU,nothing",
    "price" :  "3299",
    "lv":"qijianji",
    "type":"phone",
    "createtime":"2020-07-21",
    "tags": [ "gejiucai", "gejiujiucai", "gexinjiucai" ]
}
PUT /product/_doc/8
{
    "name" : "XS Max",
    "desc" :  "tingshuo yaochu 12 le zhongyu keyi huandiao shouli de 4S le",
    "price" :  4399,
    "lv":"qijianji",
    "type":"shouji",
    "createtime":"2020-08-19",
    "tags": [ "5V1A", "4Gquanwangtong", "big" ]
}
PUT /product/_doc/9
{
    "name" : "xiaomi TV",
    "desc" :  "Sydney's KTV",
    "price" :  2998,
    "lv":"gaoduanji",
    "type":"erji",
    "createtime":"2020-08-16",
    "tags": [ "jumo", "jiatingyingyuan", "games" ]
}
PUT /product/_doc/10
{
    "name" : "hongmi TV",
    "desc" :  "wo bishangmian nage genghuasuan,woye 2998,woye 70 cun,danshi wo genghaokan",
    "price" :  2999,
    "type":"TV",
    "lv":"gaoduanji",
    "createtime":"2020-08-28",
    "tags": [ "dapian", "languang8K", "chaobo" ]
}


相关文章
|
2月前
最小操作次数问题
最小操作次数问题
26 1
|
8月前
|
算法
面试题:如何找出数组里出现次数超过总数1/3的数
如果你每次从nums中拿出3个不一样的数作为一组,肯定会出现两种情况。一,nums被取空了,那么nums中每个数出现次数最多占总次数的1/3,写代码很好处理吧!! 二,还有剩余,这个情况就复杂了,有可能剩余多个,但是……但是,最多只可能剩余两种数。 为什么? 3个不同的数凑一组才能删掉,所以不可能删掉超过1/3的数。所以超过1/3的数肯定被剩下来,但是,剩下来的俩数并不一定都是超过1/3的,这点额外注意。
40 1
|
2月前
4.韩信点兵:有一个数,用3除余2;用5除余3;用7除余2,求满足条件的最小数
4.韩信点兵:有一个数,用3除余2;用5除余3;用7除余2,求满足条件的最小数
17 0
|
2月前
|
算法 测试技术 C#
【状态机dp】【 排序 】 2809使数组和小于等于 x 的最少时间
【状态机dp】【 排序 】 2809使数组和小于等于 x 的最少时间
剑指offer_数组---数组中出现次数超过一半的数
剑指offer_数组---数组中出现次数超过一半的数
40 0
|
索引 Python
LeetCode 599. 两个列表的最小索引总和
假设Andy和Doris想在晚餐时选择一家餐厅,并且他们都有一个表示最喜爱餐厅的列表,每个餐厅的名字用字符串表示。
80 0