golang将SQL转换为Elasticsearch DSL查询语句插件库elasticsql的使用
Golang将SQL转换为Elasticsearch DSL查询语句插件库elasticsql的使用
概述
elasticsql是一个将SQL转换为Elasticsearch DSL查询语句的Golang工具库。
功能支持
- SQL和表达式
- SQL或表达式
- 等于(=)支持
- 不等于(!=)支持
- 大于(>)支持
- 大于等于(>=)支持
- 小于(<)支持
- 小于等于(<=)支持
- SQL IN表达式(如id in (1,2,3))
- SQL NOT IN表达式(如id not in (1,2,3))
- 括号布尔支持(如where (a=1 or b=1) and (c=1 or d=1))
- SQL LIKE表达式(当前使用match phrase,未来可能改为wildcard)
- SQL ORDER BY支持
- SQL LIMIT支持
- SQL NOT LIKE表达式
- 字段缺失检查
- 支持聚合函数如count(*), count(field), min(field), max(field), avg(field)
- 支持非标准SQL聚合函数如stats(field), extended_stats(field), percentiles(field)
使用方法
安装:
go get -u github.com/cch123/elasticsql
示例代码:
package main
import (
"fmt"
"github.com/cch123/elasticsql"
)
var sql = `
select * from aaa
where a=1 and x = '三个男人'
and create_time between '2015-01-01T00:00:00+0800' and '2016-01-01T00:00:00+0800'
and process_id > 1 order by id desc limit 100,10
`
func main() {
dsl, esType, _ := elasticsql.Convert(sql)
fmt.Println(dsl)
fmt.Println(esType)
}
输出结果:
{
"query": {
"bool": {
"must": [
{
"match": {
"a": {
"query": "1",
"type": "phrase"
}
}
},
{
"match": {
"x": {
"query": "三个男人",
"type": "phrase"
}
}
},
{
"range": {
"create_time": {
"from": "2015-01-01T00:00:00+0800",
"to": "2016-01-01T00:00:00+0800"
}
}
},
{
"range": {
"process_id": {
"gt": "1"
}
}
}
]
}
},
"from": 100,
"size": 10,
"sort": [
{
"id": "desc"
}
]
}
aaa
注意事项
- 如果SQL中包含关键字(如order、timestamp等),需要使用反引号转义:
select * from `order` where `timestamp` = 1 and `desc`.id > 0
-
使用此工具需要了解Elasticsearch的term查询和match phrase查询的区别。
-
字段设置为analyzed或not analyzed会得到不同的结果。
其他信息
该工具尽量避免使用已弃用的DSL过滤器和聚合,因此与大多数Elasticsearch版本兼容。
如果有任何建议或想法,欢迎提交issue或Pull Request!
许可证
MIT
更多关于golang将SQL转换为Elasticsearch DSL查询语句插件库elasticsql的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang将SQL转换为Elasticsearch DSL查询语句插件库elasticsql的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
使用 elasticsql 将 SQL 转换为 Elasticsearch DSL
elasticsql 是一个 Go 语言库,可以将 SQL 查询语句转换为 Elasticsearch 的 DSL (Domain Specific Language) 查询语句。这对于熟悉 SQL 但需要与 Elasticsearch 交互的开发者来说非常有用。
安装 elasticsql
首先,使用 go get 安装 elasticsql:
go get github.com/cch123/elasticsql
基本使用方法
下面是一个简单的示例,展示如何将 SQL 转换为 Elasticsearch DSL:
package main
import (
"fmt"
"github.com/cch123/elasticsql"
)
func main() {
sql := "select * from my_index where age > 20 and name = 'john' limit 10"
dsl, _, err := elasticsql.Convert(sql)
if err != nil {
fmt.Println("转换失败:", err)
return
}
fmt.Println("生成的DSL:")
fmt.Println(dsl)
}
输出结果类似于:
{
"query": {
"bool": {
"must": [
{
"range": {
"age": {
"gt": 20
}
}
},
{
"term": {
"name": "john"
}
}
]
}
},
"size": 10
}
支持的功能
elasticsql 支持以下 SQL 特性:
- 基本查询:SELECT, FROM, WHERE
- 条件表达式:=, !=, >, >=, <, <=, AND, OR, NOT, IN, LIKE
- 聚合函数:COUNT, SUM, AVG, MAX, MIN
- 分组:GROUP BY
- 排序:ORDER BY
- 分页:LIMIT
更多示例
带聚合的查询
sql := "select count(*) as cnt, avg(age) as avg_age, max(age) as max_age from my_index where age > 20 group by gender"
dsl, _, err := elasticsql.Convert(sql)
带排序和分页的查询
sql := "select * from my_index where age > 20 order by age desc, name asc limit 10, 20"
dsl, _, err := elasticsql.Convert(sql)
带 IN 和 LIKE 的查询
sql := "select * from my_index where name in ('john', 'mike') and address like '%new york%'"
dsl, _, err := elasticsql.Convert(sql)
高级用法
指定索引类型
sql := "select * from my_index where age > 20"
dsl, table, err := elasticsql.ConvertWithTable(sql)
fmt.Println("索引名称:", table)
自定义转换选项
options := &elasticsql.ConvertOptions{
DefaultField: "_all", // 默认搜索字段
DefaultLimit: 100, // 默认限制
}
sql := "select * from my_index where query = 'test'"
dsl, _, err := elasticsql.ConvertWithOption(sql, options)
注意事项
- elasticsql 并不支持所有 SQL 语法,特别是复杂的 JOIN 操作
- 某些 Elasticsearch 特有的功能(如嵌套查询、地理位置查询)需要通过原生 DSL 实现
- 转换后的 DSL 可能需要根据实际需求进行微调
- 字段名中的特殊字符可能需要额外处理
完整示例
下面是一个完整的示例,展示如何将 SQL 转换为 DSL 并执行 Elasticsearch 查询:
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"github.com/cch123/elasticsql"
"github.com/olivere/elastic/v7"
)
func main() {
// 1. 转换SQL为DSL
sql := `select user, message from twitter
where retweets > 10 and user = 'kimchy'
order by retweets desc
limit 5`
dsl, table, err := elasticsql.Convert(sql)
if err != nil {
log.Fatal("转换失败:", err)
}
fmt.Println("索引:", table)
fmt.Println("生成的DSL:")
fmt.Println(dsl)
// 2. 连接到Elasticsearch
client, err := elastic.NewClient(elastic.SetURL("http://localhost:9200"))
if err != nil {
log.Fatal("连接Elasticsearch失败:", err)
}
// 3. 执行查询
var mapResp map[string]interface{}
err = json.Unmarshal([]byte(dsl), &mapResp)
if err != nil {
log.Fatal("解析DSL失败:", err)
}
searchResult, err := client.Search().
Index(table).
Source(mapResp).
Do(context.Background())
if err != nil {
log.Fatal("查询失败:", err)
}
// 4. 处理结果
fmt.Printf("查询到 %d 条结果\n", searchResult.TotalHits())
for _, hit := range searchResult.Hits.Hits {
var item map[string]interface{}
err := json.Unmarshal(hit.Source, &item)
if err != nil {
log.Printf("解析结果失败: %v", err)
continue
}
fmt.Printf("ID: %s, 数据: %v\n", hit.Id, item)
}
}
总结
elasticsql 是一个实用的工具,可以简化从 SQL 到 Elasticsearch DSL 的转换过程。虽然它不能覆盖所有 Elasticsearch 的高级查询功能,但对于大多数基本查询场景已经足够。对于更复杂的需求,你可能需要直接使用 Elasticsearch 的 DSL 或结合两者使用。
在实际项目中,建议先使用 elasticsql 进行快速原型开发,然后根据需要手动调整生成的 DSL 以获得最佳性能和功能。