golang Elasticsearch查询构建器插件库effdsl的使用

golang Elasticsearch查询构建器插件库effdsl的使用

简介

effdsl是一个用于构建Elasticsearch查询的Go语言库,它提供了简单且功能性的方式来构建查询。

GitHub Release

主要特性

  • 类型安全的查询构建:通过直观的函数调用避免容易出错的map和原始字符串字面量,增强类型安全、自动完成和编译时验证
  • 程序化查询创建:专为直接和精细的查询构建而设计,特别适用于需要以编程方式生成查询的情况
  • 全面的查询支持:涵盖大多数复合查询、全文查询和术语级别查询,并易于扩展其他类型

安装

使用Go模块支持,只需添加以下导入:

import "github.com/sdqri/effdsl/v2"

或者运行以下Go命令安装:

go get -u github.com/sdqri/effdsl/v2

使用示例

传统方式

以下是使用原始字符串的传统方式构建简单匹配查询:

import (
    es "github.com/elastic/go-elasticsearch/v8"
)

query := `{
  "query": {
    "match": {
      "message": {
        "query": "Hello World"
      }
    }
  }
}`

res, err := es.Search(
  es.Search.WithBody(strings.NewReader(query)),
)

使用effdsl

以下是使用effdsl构建相同查询的方式:

import (
    es "github.com/elastic/go-elasticsearch/v8"
    
    "github.com/sdqri/effdsl/v2"
    mq "github.com/sdqri/effdsl/v2/queries/matchquery"
)

query, err := effdsl.Define(
    effdsl.WithQuery(
        mq.MatchQuery("message", "Hello World"),
    ),
)

res, err := es.Search(
  es.Search.WithBody(strings.NewReader(query)),
)

完整示例

以下是一个更完整的示例,展示如何使用effdsl构建更复杂的查询:

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"strings"

	"github.com/elastic/go-elasticsearch/v8"
	"github.com/sdqri/effdsl/v2"
	mq "github.com/sdqri/effdsl/v2/queries/matchquery"
	bq "github.com/sdqri/effdsl/v2/queries/boolquery"
	tq "github.com/sdqri/effdsl/v2/queries/termquery"
)

func main() {
	// 初始化Elasticsearch客户端
	cfg := elasticsearch.Config{
		Addresses: []string{"http://localhost:9200"},
	}
	es, err := elasticsearch.NewClient(cfg)
	if err != nil {
		log.Fatalf("Error creating the client: %s", err)
	}

	// 使用effdsl构建复杂查询
	query, err := effdsl.Define(
		effdsl.WithQuery(
			bq.BoolQuery(
				bq.WithMust(
					mq.MatchQuery("title", "Elasticsearch"),
					tq.TermQuery("status", "published"),
				),
				bq.WithFilter(
					tq.TermQuery("category", "technology"),
				),
				bq.WithShould(
					mq.MatchQuery("content", "golang"),
					mq.MatchQuery("content", "effdsl"),
				),
				bq.WithMinimumShouldMatch(1),
			),
		),
		effdsl.WithSize(10),
		effdsl.WithFrom(0),
		effdsl.WithSort("_score", effdsl.SortDesc),
		effdsl.WithSort("publish_date", effdsl.SortDesc),
	)
	if err != nil {
		log.Fatalf("Error building query: %s", err)
	}

	// 打印生成的查询JSON
	var prettyJSON bytes.Buffer
	err = json.Indent(&prettyJSON, []byte(query), "", "  ")
	if err != nil {
		log.Fatalf("Error formatting JSON: %s", err)
	}
	fmt.Println("Generated Query:")
	fmt.Println(prettyJSON.String())

	// 执行查询
	res, err := es.Search(
		es.Search.WithBody(strings.NewReader(query)),
		es.Search.WithPretty(),
	)
	if err != nil {
		log.Fatalf("Error executing search: %s", err)
	}
	defer res.Body.Close()

	// 处理查询结果...
	fmt.Println("Search executed successfully")
}

贡献

欢迎贡献!无论是修复错误、添加新功能还是改进文档,您的帮助都是受欢迎的。

许可证

该项目采用MIT许可证。


更多关于golang Elasticsearch查询构建器插件库effdsl的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang Elasticsearch查询构建器插件库effdsl的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Elasticsearch查询构建器插件库effdsl的使用指南

effdsl是一个用于构建Elasticsearch查询的Golang库,它提供了类型安全且流畅的API来构建复杂的ES查询。下面我将详细介绍如何使用这个库。

安装

首先安装effdsl库:

go get github.com/olivere/elastic/v7
go get github.com/mailru/easyjson
go get github.com/effdsl/effdsl

基本查询构建

1. 匹配查询(Match Query)

package main

import (
	"fmt"
	"github.com/effdsl/effdsl"
)

func main() {
	// 构建一个简单的匹配查询
	query := effdsl.MatchQuery(
		effdsl.Field("title"),
		effdsl.Value("Elasticsearch"),
	)
	
	fmt.Println(query.JSON()) // 输出JSON格式的查询
}

2. 布尔查询(Bool Query)

func boolQueryExample() {
	query := effdsl.BoolQuery(
		effdsl.Must(
			effdsl.MatchQuery(
				effdsl.Field("title"),
				effdsl.Value("Elasticsearch"),
			),
		),
		effdsl.Filter(
			effdsl.TermQuery(
				effdsl.Field("status"),
				effdsl.Value("published"),
			),
		),
		effdsl.MustNot(
			effdsl.RangeQuery(
				effdsl.Field("price"),
				effdsl.Lt(100),
			),
		),
	)
	
	fmt.Println(query.JSON())
}

3. 范围查询(Range Query)

func rangeQueryExample() {
	query := effdsl.RangeQuery(
		effdsl.Field("price"),
		effdsl.Gte(100),
		effdsl.Lte(1000),
	)
	
	fmt.Println(query.JSON())
}

高级查询示例

1. 多条件组合查询

func complexQueryExample() {
	query := effdsl.BoolQuery(
		effdsl.Must(
			effdsl.MatchQuery(
				effdsl.Field("title"),
				effdsl.Value("Elasticsearch"),
			),
			effdsl.MatchQuery(
				effdsl.Field("description"),
				effdsl.Value("search engine"),
			),
		),
		effdsl.Should(
			effdsl.TermQuery(
				effdsl.Field("tags"),
				effdsl.Value("database"),
			),
			effdsl.TermQuery(
				effdsl.Field("tags"),
				effdsl.Value("nosql"),
			),
		),
		effdsl.MinimumShouldMatch(1),
		effdsl.Filter(
			effdsl.RangeQuery(
				effdsl.Field("publish_date"),
				effdsl.Gte("2022-01-01"),
			),
		),
	)
	
	fmt.Println(query.JSON())
}

2. 聚合查询

func aggregationExample() {
	query := effdsl.SearchQuery(
		effdsl.Query(
			effdsl.MatchAllQuery(),
		),
		effdsl.Aggregations(
			effdsl.TermsAggregation(
				effdsl.Name("by_category"),
				effdsl.Field("category.keyword"),
				effdsl.Size(10),
			),
			effdsl.AvgAggregation(
				effdsl.Name("avg_price"),
				effdsl.Field("price"),
			),
		),
	)
	
	fmt.Println(query.JSON())
}

与Elasticsearch客户端集成

package main

import (
	"context"
	"fmt"
	"log"
	
	"github.com/effdsl/effdsl"
	"github.com/olivere/elastic/v7"
)

func main() {
	// 创建Elasticsearch客户端
	client, err := elastic.NewClient(
		elastic.SetURL("http://localhost:9200"),
		elastic.SetSniff(false),
	)
	if err != nil {
		log.Fatal(err)
	}
	
	// 构建查询
	query := effdsl.BoolQuery(
		effdsl.Must(
			effdsl.MatchQuery(
				effdsl.Field("title"),
				effdsl.Value("Elasticsearch"),
			),
		),
		effdsl.Filter(
			effdsl.RangeQuery(
				effdsl.Field("price"),
				effdsl.Gte(100),
			),
		),
	)
	
	// 执行查询
	searchResult, err := client.Search().
		Index("products").
		Query(query).
		Pretty(true).
		Do(context.Background())
	if err != nil {
		log.Fatal(err)
	}
	
	// 处理结果
	fmt.Printf("查询到 %d 条结果\n", searchResult.TotalHits())
	for _, hit := range searchResult.Hits.Hits {
		fmt.Printf("ID: %s\n", hit.Id)
	}
}

最佳实践

  1. 链式调用:effdsl支持链式调用,可以使代码更简洁
query := effdsl.BoolQuery().
	Must(effdsl.MatchQuery("title", "Elasticsearch")).
	Filter(effdsl.RangeQuery("price").Gte(100))
  1. 复用查询片段:可以创建可复用的查询片段
func publishedFilter() effdsl.Query {
	return effdsl.TermQuery("status", "published")
}

func priceRange(min, max int) effdsl.Query {
	return effdsl.RangeQuery("price").
		Gte(min).
		Lte(max)
}
  1. 使用条件构建:根据条件动态构建查询
func buildQuery(keyword string, minPrice, maxPrice int) effdsl.Query {
	bq := effdsl.BoolQuery()
	
	if keyword != "" {
		bq.Must(effdsl.MatchQuery("title", keyword))
	}
	
	if minPrice > 0 || maxPrice > 0 {
		rq := effdsl.RangeQuery("price")
		if minPrice > 0 {
			rq.Gte(minPrice)
		}
		if maxPrice > 0 {
			rq.Lte(maxPrice)
		}
		bq.Filter(rq)
	}
	
	return bq
}

effdsl提供了类型安全且直观的方式来构建Elasticsearch查询,避免了手动拼接JSON字符串的繁琐和容易出错的问题。通过使用这个库,可以大大提高开发效率和代码的可维护性。

回到顶部