Add Search() function, README and fix some lint errors
This commit changes the internal `search()` function into an exposed `Search()` function that can be used to execute queries against an instance of an ElasticSearch client. The per-query-type methods of `Run()` are removed for now to prevent having to create them for every type. `Search()` is agnostic. A README.md file is added with some information, and a few lingering lint errors are fixed.
This commit is contained in:
parent
6c8e71c188
commit
55000abc77
|
@ -1,3 +1,5 @@
|
||||||
|
run:
|
||||||
|
tests: false
|
||||||
linters:
|
linters:
|
||||||
disable-all: true
|
disable-all: true
|
||||||
enable:
|
enable:
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
# esquery
|
||||||
|
|
||||||
|
`esquery` is an idiomatic, easy-to-use query builder for the [official Go client](https://github.com/elastic/go-elasticsearch) for [ElasticSearch](https://www.elastic.co/products/elasticsearch). It alleviates the need to use extremely nested maps of empty interfaces and serializing queries to JSON manually. It also helps eliminating common mistakes such as misspelling query types, as everything is statically typed.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
`esquery` can be used directly to build queries, with no need for external dependencies. It can execute the queries against an existing instance of `*esapi.API`, but the queries can also be manually converted to JSON if necessary.
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"bitbucket.org/scalock/esquery"
|
||||||
|
"github.com/elastic/go-elasticsearch/v7"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
es, err := elasticsearch.NewDefaultClient()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed creating client: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := esquery.Search(
|
||||||
|
es,
|
||||||
|
esquery.
|
||||||
|
Bool().
|
||||||
|
Must(esquery.Term("title", "Go and Stuff")).
|
||||||
|
Filter(esquery.Term("tag", "tech")),
|
||||||
|
es.Search.WithContext(context.TODO()),
|
||||||
|
es.Search.WithIndex("test"),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed searching for stuff: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
* Library currently supports v7 of the ElasticSearch Go client.
|
||||||
|
* The library cannot currently generate "short queries". For example, whereas
|
||||||
|
ElasticSearch can accept this:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "query": { "term": { "user": "Kimchy" } } }
|
||||||
|
```
|
||||||
|
|
||||||
|
The library will always generate this:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "query": { "term": { "user": { "value": "Kimchy" } } } }
|
||||||
|
```
|
||||||
|
|
||||||
|
This is also true for queries such as "bool", where fields like "must" can
|
||||||
|
either receive one query object, or an array of query objects. `esquery` will
|
||||||
|
generate an array even if there's only one query object.
|
||||||
|
|
||||||
|
## Supported queries
|
||||||
|
|
||||||
|
The following queries are currently supported:
|
||||||
|
|
||||||
|
| Query | `esquery` Function |
|
||||||
|
| ------------------------|---------------------- |
|
||||||
|
| `"match"` | `Match()` |
|
||||||
|
| `"match_bool_prefix"` | `MatchBoolPrefix()` |
|
||||||
|
| `"match_phrase"` | `MatchPhrase()` |
|
||||||
|
| `"match_phrase_prefix"` | `MatchPhrasePrefix()` |
|
||||||
|
| `"match_all"` | `MatchAll()` |
|
||||||
|
| `"match_none"` | `MatchNone()` |
|
||||||
|
| `"exists"` | `Exists()` |
|
||||||
|
| `"fuzzy"` | `Fuzzy()` |
|
||||||
|
| `"ids"` | `IDs()` |
|
||||||
|
| `"prefix"` | `Prefix()` |
|
||||||
|
| `"range"` | `Range()` |
|
||||||
|
| `"regexp"` | `Regexp()` |
|
||||||
|
| `"term"` | `Term()` |
|
||||||
|
| `"terms"` | `Terms()` |
|
||||||
|
| `"terms_set"` | `TermsSet()` |
|
||||||
|
| `"wildcard"` | `Wildcard()` |
|
||||||
|
| `"bool"` | `Bool()` |
|
||||||
|
| `"boosting"` | `Boosting()` |
|
||||||
|
| `"constant_score"` | `ConstantScore()` |
|
||||||
|
| `"dis_max"` | `DisMax()` |
|
9
es.go
9
es.go
|
@ -5,7 +5,8 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/elastic/go-elasticsearch/esapi"
|
"github.com/elastic/go-elasticsearch/v7"
|
||||||
|
"github.com/elastic/go-elasticsearch/v7/esapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ESQuery struct {
|
type ESQuery struct {
|
||||||
|
@ -22,7 +23,11 @@ func encode(q json.Marshaler, b *bytes.Buffer) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func search(q json.Marshaler, api *esapi.API, o ...func(*esapi.SearchRequest)) (res *esapi.Response, err error) {
|
func Search(
|
||||||
|
api *elasticsearch.Client,
|
||||||
|
q json.Marshaler,
|
||||||
|
o ...func(*esapi.SearchRequest),
|
||||||
|
) (res *esapi.Response, err error) {
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
err = encode(ESQuery{q}, &b)
|
err = encode(ESQuery{q}, &b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
6
go.mod
6
go.mod
|
@ -2,4 +2,8 @@ module bitbucket.org/scalock/esquery
|
||||||
|
|
||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require github.com/elastic/go-elasticsearch v0.0.0
|
require (
|
||||||
|
github.com/elastic/go-elasticsearch v0.0.0
|
||||||
|
github.com/elastic/go-elasticsearch/v7 v7.6.0
|
||||||
|
github.com/elastic/go-elasticsearch/v8 v8.0.0-20200210103600-aff00e5adfde
|
||||||
|
)
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -1,2 +1,6 @@
|
||||||
github.com/elastic/go-elasticsearch v0.0.0 h1:Pd5fqOuBxKxv83b0+xOAJDAkziWYwFinWnBO0y+TZaA=
|
github.com/elastic/go-elasticsearch v0.0.0 h1:Pd5fqOuBxKxv83b0+xOAJDAkziWYwFinWnBO0y+TZaA=
|
||||||
github.com/elastic/go-elasticsearch v0.0.0/go.mod h1:TkBSJBuTyFdBnrNqoPc54FN0vKf5c04IdM4zuStJ7xg=
|
github.com/elastic/go-elasticsearch v0.0.0/go.mod h1:TkBSJBuTyFdBnrNqoPc54FN0vKf5c04IdM4zuStJ7xg=
|
||||||
|
github.com/elastic/go-elasticsearch/v7 v7.6.0 h1:sYpGLpEFHgLUKLsZUBfuaVI9QgHjS3JdH9fX4/z8QI8=
|
||||||
|
github.com/elastic/go-elasticsearch/v7 v7.6.0/go.mod h1:OJ4wdbtDNk5g503kvlHLyErCgQwwzmDtaFC4XyOxXA4=
|
||||||
|
github.com/elastic/go-elasticsearch/v8 v8.0.0-20200210103600-aff00e5adfde h1:Y9SZx8RQqFycLxi5W5eFmxMqnmijULVc3LMjBTtZQdM=
|
||||||
|
github.com/elastic/go-elasticsearch/v8 v8.0.0-20200210103600-aff00e5adfde/go.mod h1:xe9a/L2aeOgFKKgrO3ibQTnMdpAeL0GC+5/HpGScSa4=
|
||||||
|
|
8
match.go
8
match.go
|
@ -5,8 +5,6 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/elastic/go-elasticsearch/esapi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
@ -51,10 +49,6 @@ func (a MatchQuery) MarshalJSON() ([]byte, error) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *MatchQuery) Run(api *esapi.API, o ...func(*esapi.SearchRequest)) (res *esapi.Response, err error) {
|
|
||||||
return search(*a, api, o...)
|
|
||||||
}
|
|
||||||
|
|
||||||
type matchParams struct {
|
type matchParams struct {
|
||||||
Qry interface{} `json:"query"`
|
Qry interface{} `json:"query"`
|
||||||
Anl string `json:"analyzer,omitempty"`
|
Anl string `json:"analyzer,omitempty"`
|
||||||
|
@ -89,7 +83,7 @@ func MatchPhrasePrefix(fieldName string, simpleQuery ...interface{}) *MatchQuery
|
||||||
|
|
||||||
func newMatch(mType matchType, fieldName string, simpleQuery ...interface{}) *MatchQuery {
|
func newMatch(mType matchType, fieldName string, simpleQuery ...interface{}) *MatchQuery {
|
||||||
var qry interface{}
|
var qry interface{}
|
||||||
if simpleQuery != nil && len(simpleQuery) > 0 {
|
if len(simpleQuery) > 0 {
|
||||||
qry = simpleQuery[len(simpleQuery)-1]
|
qry = simpleQuery[len(simpleQuery)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,6 @@ package esquery
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/elastic/go-elasticsearch/esapi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-all-query.html
|
// https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-all-query.html
|
||||||
|
@ -28,10 +26,6 @@ func (a MatchAllQuery) MarshalJSON() ([]byte, error) {
|
||||||
return json.Marshal(map[string]matchAllParams{mType: a.params})
|
return json.Marshal(map[string]matchAllParams{mType: a.params})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *MatchAllQuery) Run(api *esapi.API, o ...func(*esapi.SearchRequest)) (res *esapi.Response, err error) {
|
|
||||||
return search(*a, api, o...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MatchAll() *MatchAllQuery {
|
func MatchAll() *MatchAllQuery {
|
||||||
return &MatchAllQuery{all: true}
|
return &MatchAllQuery{all: true}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue