求问一个 es 嵌套文档查询,仅当查询范围内所有嵌套文档都满足条件时才返回,而不是只要有一个嵌套文档满足条件就返回。
我的场景是按天建立嵌套文档,筛选时给定日期范围,需要筛选出该日期范围内每天都满足筛选条件的文档,目前我自己写的搜索语法只要日期范围内有一天满足就会返回..
我的文档结构如下:
{
"mappings": {
"properties": {
"adResource": {
"type": "nested",
"properties": {
"day": {
"type": "date",
"format": "yyyy-MM-dd || epoch_millis"
},
"total": {
"type": "integer"
},
"subResource": {
"type": "nested",
"properties": {
"hours": {
"type": "integer"
},
"total": {
"type": "integer"
}
}
}
}
}
}
}
}
数据示例:
{
"adResource": [
{
"total": 1800,
"subResource": [
{
"hours": 0,
"total": 0
},
{
"hours": 3600,
"total": 0
},
{
"hours": 7200,
"total": 0
},
{
"hours": ...,
"total": ...
},
{
"hours": 82800,
"total": 0
}
"day": "2021-11-20"
},
{
"total": 5200,
"subResource":[......]
"day": "2021-11-21"
}
]
}
需求:检索的时候给定一个日期区间和小时区间,要求检索出日期区间和小时区间内资源全部满足的文档,例如给定检索条件:
{
"dayStart": "2021-11-20",
"dayEnd": "2021-11-21",
"total": 540,
"subResource": [
{
"hour": 0,
"total": 180
},
{
"hour": 3600, // hour 3600 表示 1:00:00 到 1:59:59 的区间
"total": 360
}
]
}
表示 20 、21 这两天的 total>540 ,且这两天内的 hour 0 > 180 && hour 3600 > 360
目前的搜索语法如下,该搜索会返回 20 、21 这两天只有一天满足条件的文档,而我需要的是两天都满足的文档:
{
"query": {
"bool": {
"filter": [
{
"nested": {
"path": "adResource",
"query": {
"bool": {
"must": [
{
"range": {
"adResource.day": {
"gte": "2021-11-20",
"lte": "2021-11-21"
}
}
},
{
"nested": {
"path": "adResource.subResource",
"query": {
"bool": {
"must": [
{
"bool": {
"must": [
{
"term": {
"adResource.subResource.hours": {
"value": "0"
}
}
},
{
"range": {
"adResource.subResource.total": {
"gte": 180
}
}
}
]
}
},
{
"bool": {
"must": [
{
"term": {
"adResource.subResource.hours": {
"value": "3600"
}
}
},
{
"range": {
"adResource.subResource.total": {
"gte": 360
}
}
}
]
}
}
]
}
}
}
}
]
}
}
}
}
]
}
}
}
1
Saxton 2021-11-22 14:54:40 +08:00
'''
{ "bool":{ "must":[ { "term":{ "adResource.subResource.hours":{ "value":"0" } } }, { "range":{ "adResource.subResource.total":{ "gte":180 } } } ] } } ''' 为什么这里有一个 "value":"0" 呢 |
2
Saxton 2021-11-22 15:06:54 +08:00
你想要查询表示 20 、21 这两天的 total>540 ,且这两天内的 hour 0 > 180 && hour 3600 > 360 ,解析一下你的条件,20 、21 这两天的 total>540 这个为必要条件, 那么 hour 0 > 180 && hour 3600 > 360 应该为或条件,而不是且
|
3
CRUD OP @Saxton value 0 表示的是 00:00-00:59 这段时间,我是把距离 0 点的秒数当做了小时的 key ,比如 0 表示 0 点到 1 点,3600 表示 1 点到 2 点,7200 表示 2 点到 3 点。
实际上 hour 0 > 180 && hour 3600 > 360 也是为且的,因为我需要的是在 0 点-1 点,1 点-2 点这个区间都满足的数据。 |
4
sadfQED2 2021-11-23 18:51:41 +08:00 via Android
我最近也被 es 的反人类查询语法折腾得死去活来,最后想了个办法,先用 sql 写出查询语句,再用最新的 es sql api 转成 dsl 语句
https://xjiangwei.cn/2021/11/23/ES_DSL/ |