关于在写一个查询模版es案例时踩的坑!

背景: Elasticsearch 的查询模板(Search Template)功能非常强大,可以让你参数化复杂的查询,从而在不同的上下文中重用相同的查询逻辑。以下是一个从 Elasticsearch 官方文档中提取的查询模板案例,涵盖了如何创建和使用查询模板。

目前项目采用的es版本:Elasticsearch 6.8.6

1. 创建查询模板

首先,我们需要创建一个查询模板。假设我们有一个索引 event_index,其中包含 user_iduser_namecreate_time 字段。我们希望统计在某个时间范围内用户的唯一数量。

创建索引映射
PUT /event_index
{
  "mappings": {
    "properties": {
      "user_id": {
        "type": "keyword"
      },
      "create_time": {
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss"
      },
      "user_name": {
        "type": "text"
      }
    }
  }
}
插入示例数据
PUT /event_index/_doc/1
{
  "user_id": "1",
  "user_name": "format1",
  "create_time": "2015-11-07 12:00:00"
}

PUT /event_index/_doc/2
{
  "user_id": "2",
  "user_name": "format2",
  "create_time": "2015-11-07 13:30:00"
}

PUT /event_index/_doc/3
{
  "user_id": "3",
  "user_name": "format3",
  "create_time": "2015-11-07 13:30:00"
}

PUT /event_index/_doc/4
{
  "user_id": "1",
  "user_name": "format1",
  "create_time": "2015-11-07 13:50:00"
}

PUT /event_index/_doc/5
{
  "user_id": "1",
  "user_name": "format1",
  "create_time": "2015-11-07 13:55:00"
}
创建查询模板
PUT _scripts/stats
{
  "script": {
    "lang": "mustache",
    "source": {
      "query": {
        "bool": {
          "must": [
            {
              "range": {
                "create_time": {
                  "gte": "{{start_date}}",
                  "lte": "{{end_date}}"
                }
              }
            }
          ]
        }
      },
      "size": 0,
      "aggs": {
        "stats_data": {
          "date_histogram": {
            "field": "create_time",
            "calendar_interval": "{{interval}}"
          },
          "aggs": {
            "unique_users": {
              "cardinality": {
                "field": "user_id"
              }
            }
          }
        }
      }
    }
  }
}

2. 使用查询模板

查询以小时为单位
GET _search/template
{
  "id": "stats",
  "params": {
    "start_date": "2015-11-07 00:00:00",
    "end_date": "2015-11-07 23:59:59",
    "interval": "hour"
  }
}
查询以天为单位
GET _search/template
{
  "id": "stats",
  "params": {
    "start_date": "2015-11-07 00:00:00",
    "end_date": "2015-11-07 23:59:59",
    "interval": "day"
  }
}

3. 解释

  • 创建索引映射:定义了 event_index 索引的字段类型和格式。
  • 插入示例数据:向 event_index 索引中插入了一些示例数据。
  • 创建查询模板:定义了一个查询模板 stats,使用 Mustache 语言参数化了查询条件和聚合条件。
    • range 查询用于筛选在指定时间范围内的数据。
    • date_histogram 聚合用于按时间间隔(小时或天)统计数据。
    • cardinality 聚合用于统计唯一用户数。
  • 使用查询模板:通过 GET _search/template 请求调用查询模板,并传入参数 start_dateend_date 和 interval

4.遇到的版本问题

执行上述案例[1:185] [date_histogram] unknown field [calendar_interval], parser not found

在 Elasticsearch 6.8.6 版本中,date_histogram 聚合确实没有 calendar_interval 参数。取而代之的是使用 interval 参数来指定时间间隔。上述案例的查询在另一个师兄的较高版本的es里执行是可以哦.

让我们更新查询模板,使用 interval 参数来指定时间间隔。

更新查询模板

calendar_interval 替换为 interval

PUT _scripts/stats
{
  "script": {
    "lang": "mustache",
    "source": {
      "query": {
        "bool": {
          "must": [
            {
              "range": {
                "create_time": {
                  "gte": "{{start_date}}",
                  "lte": "{{end_date}}"
                }
              }
            }
          ]
        }
      },
      "size": 0,
      "aggs": {
        "stats_data": {
          "date_histogram": {
            "field": "create_time",
            "interval": "{{interval}}"
          },
          "aggs": {
            "unique_users": {
              "cardinality": {
                "field": "user_id"
              }
            }
          }
        }
      }
    }
  }
}

5. 输出示例

以小时为单位的输出
{
  "took": 3,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 5,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "stats_data": {
      "buckets": [
        {
          "key_as_string": "2015-11-07 12:00:00",
          "key": 1446897600000,
          "doc_count": 1,
          "unique_users": {
            "value": 1
          }
        },
        {
          "key_as_string": "2015-11-07 13:00:00",
          "key": 1446901200000,
          "doc_count": 4,
          "unique_users": {
            "value": 3
          }
        }
      ]
    }
  }
}
以天为单位的输出
{
  "took": 4,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 5,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "stats_data": {
      "buckets": [
        {
          "key_as_string": "2015-11-07 00:00:00",
          "key": 1446854400000,
          "doc_count": 5,
          "unique_users": {
            "value": 3
          }
        }
      ]
    }
  }
}

5.总结

通过这个案例,你可以看到如何使用 Elasticsearch 的查询模板来参数化复杂的查询,并在不同的上下文中重用这些查询。查询模板不仅可以简化应用,还可以封装复杂的业务逻辑,提高开发效率。希望这个案例对你有所帮助!如果有更多问题或需要进一步的帮助,请随时告诉我。

6.后续:es如何实现java应用端的模板查询?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值