Skip to content

Commit

Permalink
Implement using the official Elasticsearch library.
Browse files Browse the repository at this point in the history
Create a new implementation using the official Elasticsearch library in a
separate package, without impacting those who use the Olivere implementation.

Refine the abstraction of Elasticsearch Search functionality even more,
enabling the use of this library only.
  • Loading branch information
victormn committed Jul 3, 2024
1 parent 6531587 commit e164b75
Show file tree
Hide file tree
Showing 29 changed files with 2,713 additions and 104 deletions.
106 changes: 3 additions & 103 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

## <a name="Description" /> 1. Description

ElasticUtil is a generic library that assists in the use of Elasticsearch, using olivere/elastic library. It is possible to create olivere/elastic's queries using only one struct. It is also possible to translate errors and responses.
ElasticUtil is a generic library that assists in the use of Elasticsearch, using olivere/elastic library and the offical library. It is possible to create elastic's queries using only one struct. It is also possible to translate errors and responses.

## <a name="TechnologyStack" /> 2. Technology Stack

Expand Down Expand Up @@ -46,111 +46,11 @@ ElasticUtil is a generic library that assists in the use of Elasticsearch, using
go mod tidy
```

- ### <a name="Usage" /> Usage

- Import the package

```go
import (
"github.com/arquivei/elasticutil"
)
```

- Define a filter struct

```go
type ExampleFilterMust struct {
Names []string `es:"Name"`
SocialNames []string `es:"SocialName"`
Ages []uint64 `es:"Age"`
HasCovid *bool
CreatedAt *elasticutil.TimeRange
AgeRange *elasticutil.IntRange `es:"Age"`
CovidInfo elasticutil.Nested `es:"Covid"`
NameOrSocialName elasticutil.FullTextSearchShould `es:"Name,SocialName"`
}
type ExampleFilterExists struct {
HasCovidInfo elasticutil.Nested `es:"Covid"`
HasAge *bool `es:"Age"`
}
type ExampleCovidInfo struct {
HasCovidInfo *bool `es:"Covid"`
Symptoms []string `es:"Covid.Symptom"`
FirstSymptomDate *elasticutil.TimeRange `es:"Covid.Date"`
}
```

- And now, it's time!
```go
requestFilter := elasticutil.Filter{
Must: ExampleFilterMust{
Names: []string{"John", "Mary"},
Ages: []uint64{16, 17, 18, 25, 26},
HasCovid: refBool(true),
CovidInfo: elasticutil.NewNested(
ExampleCovidInfo{
Symptoms: []string{"cough"},
FirstSymptomDate: &elasticutil.TimeRange{
From: time.Date(2019, time.November, 28, 15, 27, 39, 49, time.UTC),
To: time.Date(2020, time.November, 28, 15, 27, 39, 49, time.UTC),
},
},
),
CreatedAt: &elasticutil.TimeRange{
From: time.Date(2020, time.November, 28, 15, 27, 39, 49, time.UTC),
To: time.Date(2021, time.November, 28, 15, 27, 39, 49, time.UTC),
},
AgeRange: &elasticutil.IntRange{
From: 15,
To: 30,
},
NameOrSocialName: elasticutil.NewFullTextSearchShould([]string{"John", "Mary", "Rebecca"}),
},
MustNot: ExampleFilterMust{
Names: []string{"Lary"},
AgeRange: &elasticutil.IntRange{
From: 29,
To: 30,
},
},
Exists: ExampleFilterExists{
HasCovidInfo: elasticutil.NewNested(
ExampleCovidInfo{
HasCovidInfo: refBool(true),
},
),
HasAge: refBool(true),
},
}
// BuildElasticBoolQuery builds a olivere/elastic's query based on Filter.
elasticQuery, err := elasticutil.BuildElasticBoolQuery(context.Background(), requestFilter)
if err != nil {
panic(err)
}

// MarshalQuery transforms a olivere/elastic's query in a string for log and test
// purpose.
verboseElasticQuery := elasticutil.MarshalQuery(elasticQuery)

fmt.Println(verboseElasticQuery)
```

- ### <a name="Examples" /> Examples

- [Sample usage](https://github.com/arquivei/elasticutil/blob/master/examples/main.go)
- [Olivere](https://github.com/arquivei/elasticutil/blob/master/examples/olivere/main.go)

## <a name="Changelog" /> 4. Changelog

- **ElasticUtil 0.1.0 (May 27, 2022)**

- [New] Decoupling this package from Arquivei's API projects.
- [New] Setting github's workflow with golangci-lint
- [New] Example for usage.
- [New] Documents: Code of Conduct, Contributing, License and Readme.
- [Official library](https://github.com/arquivei/elasticutil/blob/master/examples/official/main.go)

## <a name="Collaborators" /> 5. Collaborators

Expand Down
81 changes: 81 additions & 0 deletions examples/official/filter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package main

import (
"time"

elasticutil "github.com/arquivei/elasticutil/official/v7"
"github.com/arquivei/elasticutil/official/v7/querybuilders"
)

type ExampleFilterMust struct {
Names []string `es:"Name"`
SocialNames []string `es:"SocialName"`
Ages []uint64 `es:"Age"`
HasCovid *bool
CreatedAt *elasticutil.TimeRange
AgeRange *elasticutil.IntRange `es:"Age"`
CovidInfo elasticutil.Nested `es:"Covid"`
NameOrSocialName elasticutil.FullTextSearchShould `es:"Name,SocialName"`
MyCustomSearch elasticutil.CustomSearch
}

type ExampleFilterExists struct {
HasCovidInfo elasticutil.Nested `es:"Covid"`
HasAge *bool `es:"Age"`
}

type ExampleCovidInfo struct {
HasCovidInfo *bool `es:"Covid"`
Symptoms []string `es:"Covid.Symptom"`
FirstSymptomDate *elasticutil.TimeRange `es:"Covid.Date"`
}

func createFilter() elasticutil.Filter {
return elasticutil.Filter{
Must: ExampleFilterMust{
Names: []string{"John", "Mary"},
Ages: []uint64{16, 17, 18, 25, 26},
HasCovid: refBool(true),
CovidInfo: elasticutil.NewNested(
ExampleCovidInfo{
Symptoms: []string{"cough"},
FirstSymptomDate: &elasticutil.TimeRange{
From: time.Date(2019, time.November, 28, 15, 27, 39, 49, time.UTC),
To: time.Date(2020, time.November, 28, 15, 27, 39, 49, time.UTC),
},
},
),
CreatedAt: &elasticutil.TimeRange{
From: time.Date(2020, time.November, 28, 15, 27, 39, 49, time.UTC),
To: time.Date(2021, time.November, 28, 15, 27, 39, 49, time.UTC),
},
AgeRange: &elasticutil.IntRange{
From: 15,
To: 30,
},
NameOrSocialName: elasticutil.NewFullTextSearchShould([]string{"John", "Mary", "Rebecca"}),
MyCustomSearch: elasticutil.NewCustomSearch(func() (querybuilders.Query, error) {
return querybuilders.NewBoolQuery().Must(querybuilders.NewTermQuery("Name", "John")), nil
}),
},
MustNot: ExampleFilterMust{
Names: []string{"Lary"},
AgeRange: &elasticutil.IntRange{
From: 29,
To: 30,
},
},
Exists: ExampleFilterExists{
HasCovidInfo: elasticutil.NewNested(
ExampleCovidInfo{
HasCovidInfo: refBool(true),
},
),
HasAge: refBool(true),
},
}
}

func refBool(b bool) *bool {
return &b
}
36 changes: 36 additions & 0 deletions examples/official/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package main

import (
"context"
"fmt"

elasticutil "github.com/arquivei/elasticutil/official/v7"
)

func main() {
client := elasticutil.MustNewClient("")

response, err := client.Search(
context.Background(),
elasticutil.SearchConfig{
Filter: createFilter(),
Indexes: []string{""},
Size: 5,
IgnoreUnavailable: true,
AllowNoIndices: true,
TrackTotalHits: true,
Sort: elasticutil.Sorters{
Sorters: []elasticutil.Sorter{
{
Field: "ID",
Ascending: true,
},
},
},
SearchAfter: "",
},
)

fmt.Println(response, err)

}
File renamed without changes.
5 changes: 4 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,22 @@ toolchain go1.21.3

require (
github.com/arquivei/foundationkit v0.6.1
github.com/elastic/go-elasticsearch/v7 v7.17.10
github.com/olivere/elastic/v7 v7.0.32
github.com/rs/zerolog v1.31.0
github.com/stretchr/testify v1.9.0
)

require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/go-kit/kit v0.13.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/rs/zerolog v1.31.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
golang.org/x/sys v0.16.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ github.com/arquivei/foundationkit v0.6.1/go.mod h1:OC6R9oJgGD8C+HTNAZcZaV6lZCk+3
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/elastic/go-elasticsearch/v7 v7.17.10 h1:TCQ8i4PmIJuBunvBS6bwT2ybzVFxxUhhltAs3Gyu1yo=
github.com/elastic/go-elasticsearch/v7 v7.17.10/go.mod h1:OJ4wdbtDNk5g503kvlHLyErCgQwwzmDtaFC4XyOxXA4=
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/go-kit/kit v0.13.0 h1:OoneCcHKHQ03LfBpoQCUfCluwd2Vt3ohz+kvbJneZAU=
github.com/go-kit/kit v0.13.0/go.mod h1:phqEHMMUbyrCFCTgH48JueqrM3md2HcAZ8N3XE4FKDg=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
Expand All @@ -26,6 +30,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A=
github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand Down
45 changes: 45 additions & 0 deletions official/v7/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package v7

import (
"context"
"net/http"

"github.com/arquivei/elasticutil/official/v7/internal/retrier"
es "github.com/elastic/go-elasticsearch/v7"
)

// Client represents the Elasticsearch's client of the official lib.
type Client interface {
Search(context.Context, SearchConfig) (SearchResponse, error)
}

type esClient struct {
client *es.Client
}

// NewClient returns a new Client using the @urls.
func NewClient(urls ...string) (Client, error) {
client, err := es.NewClient(es.Config{
Addresses: urls,
RetryBackoff: retrier.NewSimpleBackoff(10, 100),
Transport: &http.Transport{
DisableCompression: false,
},
})
if err != nil {
return nil, err
}
return &esClient{
client: client,
}, nil
}

// MustNewClient returns a new Client using the @urls. It panics
// instead of returning an error.
func MustNewClient(urls ...string) Client {
client, err := NewClient(urls...)
if err != nil {
panic(err)
}
return client
}
24 changes: 24 additions & 0 deletions official/v7/client_mock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package v7

import (
"context"

"github.com/stretchr/testify/mock"
)

type mockClient struct {
mock.Mock
}

func (m *mockClient) Search(_ context.Context, sc SearchConfig) (SearchResponse, error) {
args := m.Called(sc)
return args.Get(0).(SearchResponse), args.Error(1)
}

// MustNewClientMock returns a mocked Client that uses Search method and returns @expectedResponse
// and @expectedError for the giving @input.
func MustNewClientMockSearch(input SearchConfig, expectedResponse SearchResponse, expectedError error) Client {
m := mockClient{}
m.On("Search", input).Return(expectedResponse, expectedError)
return &m
}
Loading

0 comments on commit e164b75

Please sign in to comment.