es painless 聚合查询 脚本查询 聚合结果求和

我需要通过一次ES查询, 完成如下场景:

统计一个公司下各个部门的人数分布, 并需要统计各个部门的1月份在职人数, 入职, 离职人数, 以及公司总共的在职, 入职, 离职人数

具体条件如下(做了简化处理)

  • 查询出的人员需要为指定公司 id 的人员(条件中的 c_company_id 表示)
  • 部门统计需要统计值为空的人数(脚本的 "missing": "未填写" 表示)
  • 员工只存储了入/离日期字段
  • 月初在职人数(employed_origin 表示)
    • 对于 c_status 字段在 [1, 2] 区间内(非离职人员), 并且入职日期小于 2020-01-01, 该员工计入在职人数
    • 对于 c_status3 的员工(离职人员), 如果他的离职日期大于 2020-01-01 并且入职日期小于 2020-02-01, 那么该员工计入在职员工
  • 入职人数(hire 表示)
    • 入职日期介于 2020-01-012020-02-01 之间的人数
  • 离职人数(leave 表示)
    • c_status3 并且离职日期介于 2020-01-012020-02-01 之间的人数
  • 月末在职人数(这才是真正需要的在职人数的值)
    • 月初在职人数 + 入职人数 - 离职人数
  • 最后几个 sum_bucket 表示全公司的求和统计

在搜索引擎数小时的帮助下, 最终将上述条件成功写进 ES 的查询语句中, 并且满足性能要求, 在此做个记录

GET my_index/_search
	{
	  "track_total_hits": 100000,
	  "query": {
	    "bool": {
	      "must": [
	        {
	          "term": {
	            "c_company_id": "xxxxxxxxxxxxx"
	          }
	        }
	      ]
	    }
	  },
	  "size": 0,
	  "aggs": {
	    "department_id": {
	      "terms": {
	        "field": "c_department_id",
	        "size" : 3000,
	        "missing": "未填写"
	      },
	      "aggs": {
	        "employed_origin": {
	          "sum": {
	            "script": {
	              "lang": "painless",
	              "source": "def lower_ms = Instant.parse(params.lower_date + \"T00:00:00.00Z\").toEpochMilli();        if (doc.containsKey('c_work_status') && doc['c_work_status'].size() > 0 && doc.containsKey('c_hire_dt') && doc['c_hire_dt'].size() > 0 && doc['c_hire_dt'].value.toInstant().toEpochMilli() < lower_ms)        {            if (1 <= doc['c_work_status'].value && doc['c_work_status'].value <= 2)            { return 1; }            else if (doc['c_work_status'].value == 4 && doc.containsKey('c_leave_dt') && doc['c_leave_dt'].size() > 0 && doc['c_leave_dt'].value.toInstant().toEpochMilli() >= lower_ms)            { return 1; }            else            { return 0; }        }        else         { return 0; }",
	              "params": {
	                "upper_date": "2020-02-01",
	                "lower_date": "2020-01-01"
	              }
	            }
	          }
	        },
	        "hire": {
	          "sum": {
	            "script": {
	              "lang": "painless",
	              "source": "def lower_ms = Instant.parse(params.lower_date + \"T00:00:00.00Z\").toEpochMilli(); def upper_ms = Instant.parse(params.upper_date + \"T00:00:00.00Z\").toEpochMilli(); if (doc.containsKey('c_hire_dt') && doc['c_hire_dt'].size() > 0 && doc['c_hire_dt'].value.toInstant().toEpochMilli() >= lower_ms && doc['c_hire_dt'].value.toInstant().toEpochMilli() < upper_ms) { return 1; } else { return 0; }",
	              "params": {
	                "upper_date": "2020-02-01",
	                "lower_date": "2020-01-01"
	              }
	            }
	          }
	        },
	        "leave": {
	          "sum": {
	            "script": {
	              "lang": "painless",
	              "source": "def lower_ms = Instant.parse(params.lower_date + \"T00:00:00.00Z\").toEpochMilli(); def upper_ms = Instant.parse(params.upper_date + \"T00:00:00.00Z\").toEpochMilli(); if (doc.containsKey('c_work_status') && doc['c_work_status'].size() > 0 && doc['c_work_status'].value == 3 && doc.containsKey('c_leave_dt') && doc['c_leave_dt'].size() > 0 && doc['c_leave_dt'].value.toInstant().toEpochMilli() >= lower_ms && doc['c_leave_dt'].value.toInstant().toEpochMilli() < upper_ms) { return 1; } else { return 0; }",
	              "params": {
	                "upper_date": "2020-02-01",
	                "lower_date": "2020-01-01"
	              }
	            }
	          }
	
	        },
	        "employed": {
	                "bucket_script": {
	                    "buckets_path": {
	                        "employed_origin": "employed_origin",
	                        "hire": "hire",
	                        "leave": "leave"
	                    },
	                    "script": "params.employed_origin + params.hire - params.leave"
	                }
	            }
	      }
	    },
	    "employed_origin": {
	      "sum_bucket": {
	        "buckets_path": "department_id>employed_origin"
	      }
	    },
	    "employed": {
	      "sum_bucket": {
	        "buckets_path": "department_id>employed"
	      }
	    },
	    "hire": {
	      "sum_bucket": {
	        "buckets_path": "department_id>hire"
	      }
	    },
	    "leave": {
	      "sum_bucket": {
	        "buckets_path": "department_id>leave"
	      }
	    }
	  }
	}

你可能感兴趣的:(es)