Commit b076c1ec authored by ale's avatar ale
Browse files

Update github.com/olivere/elastic

parent 2ecac0a6
......@@ -2,4 +2,4 @@ module git.autistici.org/ai3/tools/logcat
// go: no requirements found in vendor/vendor.json
require github.com/olivere/elastic/v7 v7.0.15
require github.com/olivere/elastic/v7 v7.0.19
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/aws/aws-sdk-go v1.30.7/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/aws/aws-sdk-go v1.33.5/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
......@@ -12,20 +13,28 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
github.com/mailru/easyjson v0.7.1 h1:mdxE1MF9o53iCb2Ghj1VfWvh7ZOwHpnVG/xwXrV90U8=
github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/olivere/elastic/v7 v7.0.15 h1:v7kX5S+oMFfYKS4ZyzD37GH6lfZSpBo9atynRwBUywE=
github.com/olivere/elastic/v7 v7.0.15/go.mod h1:+FgncZ8ho1QF3NlBo77XbuoTKYHhvEOfFZKIAfHnnDE=
github.com/olivere/elastic/v7 v7.0.19 h1:w4F6JpqOISadhYf/n0NR1cNj73xHqh4pzPwD1Gkidts=
github.com/olivere/elastic/v7 v7.0.19/go.mod h1:4Jqt5xvjqpjCqgnTcHwl3j8TLs8mvoOK8NYgo/qEOu4=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/smartystreets/assertions v1.1.1/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM=
github.com/smartystreets/gunit v1.3.4/go.mod h1:ZjM1ozSIMJlAz/ay4SG8PeKF00ckUp+zMHZXV9/bvak=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
......
sudo: required
language: go
go:
- "1.13.x"
- "1.14.x"
- tip
matrix:
allow_failures:
- go: tip
env:
- GO111MODULE=on
- GO111MODULE=off
addons:
apt:
update: true
packages:
- docker-ce
services:
- docker
before_install:
- if [[ "$TRAVIS_OS_NAME" == "linux" && ! $(which nc) ]] ; then sudo apt-get install -y netcat ; fi
- sudo sysctl -w vm.max_map_count=262144
- docker-compose pull
- docker-compose up -d
- go get -u github.com/google/go-cmp/cmp
- go get -u github.com/fortytw2/leaktest
- go get . ./aws/... ./config/... ./trace/... ./uritemplates/...
- while ! nc -z localhost 9200; do sleep 1; done
- while ! nc -z localhost 9210; do sleep 1; done
install: true # ignore the go get -t -v ./...
script:
- go test -race -deprecations -strict-decoder -v . ./aws/... ./config/... ./trace/... ./uritemplates/...
......@@ -40,6 +40,7 @@ Bryan Conklin [@bmconklin](https://github.com/bmconklin)
Bruce Zhou [@brucez-isell](https://github.com/brucez-isell)
Carl Dunham [@carldunham](https://github.com/carldunham)
Carl Johan Gustavsson [@cjgu](https://github.com/cjgu)
Carson [@carson0321](https://github.com/carson0321)
Cat [@cat-turner](https://github.com/cat-turner)
César Jiménez [@cesarjimenez](https://github.com/cesarjimenez)
cforbes [@cforbes](https://github.com/cforbes)
......@@ -56,6 +57,7 @@ Connor Peet [@connor4312](https://github.com/connor4312)
Conrad Pankoff [@deoxxa](https://github.com/deoxxa)
Corey Scott [@corsc](https://github.com/corsc)
Chris Petersen [@ex-nerd](https://github.com/ex-nerd)
czxichen [@czxichen](https://github.com/czxichen)
Daniel Barrett [@shendaras](https://github.com/shendaras)
Daniel Heckrath [@DanielHeckrath](https://github.com/DanielHeckrath)
Daniel Imfeld [@dimfeld](https://github.com/dimfeld)
......
......@@ -359,10 +359,10 @@ Here are a few tips on how to get used to Elastic:
- [x] Script Score Query
- [x] Percolate Query
- Span queries
- [ ] Span Term Query
- [x] Span Term Query
- [ ] Span Multi Term Query
- [ ] Span First Query
- [ ] Span Near Query
- [x] Span First Query
- [x] Span Near Query
- [ ] Span Or Query
- [ ] Span Not Query
- [ ] Span Containing Query
......
......@@ -4,7 +4,10 @@
package elastic
import "net/url"
import (
"net/url"
"strings"
)
// canonicalize takes a list of URLs and returns its canonicalized form, i.e.
// remove anything but scheme, userinfo, host, path, and port.
......@@ -14,15 +17,17 @@ import "net/url"
// Example:
// http://127.0.0.1:9200/?query=1 -> http://127.0.0.1:9200
// http://127.0.0.1:9200/db1/ -> http://127.0.0.1:9200/db1
// http://127.0.0.1:9200/db1/// -> http://127.0.0.1:9200/db1
func canonicalize(rawurls ...string) []string {
var canonicalized []string
for _, rawurl := range rawurls {
u, err := url.Parse(rawurl)
if err == nil {
if u.Scheme == "http" || u.Scheme == "https" {
// Trim trailing slashes
for len(u.Path) > 0 && u.Path[len(u.Path)-1] == '/' {
u.Path = u.Path[0 : len(u.Path)-1]
// Trim trailing slashes. Notice that strings.TrimSuffix will only remove the last slash,
// not all slashes from the suffix, so we'll loop over the path to remove all slashes.
for strings.HasSuffix(u.Path, "/") {
u.Path = u.Path[:len(u.Path)-1]
}
u.Fragment = ""
u.RawQuery = ""
......
......@@ -316,6 +316,8 @@ type CatShardsResponseRow struct {
WarmerCurrent int `json:"warmer.current,string"` // current warmer ops on primaries & replicas
WarmerTotal int `json:"warmer.total,string"` // total warmer ops on primaries & replicas
WarmerTotalTime string `json:"warmer.total_time"` // time spent in warmers on primaries & replicas, e.g. "47s"
PathData string `json:"path.data"`
PathState string `json:"path.state"`
}
// catShardsResponseRowAliasesMap holds the global map for columns aliases
......
......@@ -25,7 +25,7 @@ import (
const (
// Version is the current version of Elastic.
Version = "7.0.15"
Version = "7.0.19"
// DefaultURL is the default endpoint of Elasticsearch on the local machine.
// It is used e.g. when initializing a new Client without a specific URL.
......@@ -139,7 +139,6 @@ type Client struct {
snifferCallback SnifferCallback // callback to modify the sniffing decision
snifferStop chan bool // notify sniffer to stop, and notify back
decoder Decoder // used to decode data sent from Elasticsearch
basicAuth bool // indicates whether to send HTTP Basic Auth credentials
basicAuthUsername string // username for HTTP Basic Auth
basicAuthPassword string // password for HTTP Basic Auth
sendGetBodyAs string // override for when sending a GET with a body
......@@ -265,11 +264,10 @@ func NewSimpleClient(options ...ClientOptionFunc) (*Client, error) {
c.urls = canonicalize(c.urls...)
// If the URLs have auth info, use them here as an alternative to SetBasicAuth
if !c.basicAuth {
if c.basicAuthUsername == "" && c.basicAuthPassword == "" {
for _, urlStr := range c.urls {
u, err := url.Parse(urlStr)
if err == nil && u.User != nil {
c.basicAuth = true
c.basicAuthUsername = u.User.Username()
c.basicAuthPassword, _ = u.User.Password()
break
......@@ -351,11 +349,10 @@ func DialContext(ctx context.Context, options ...ClientOptionFunc) (*Client, err
c.urls = canonicalize(c.urls...)
// If the URLs have auth info, use them here as an alternative to SetBasicAuth
if !c.basicAuth {
if c.basicAuthUsername == "" && c.basicAuthPassword == "" {
for _, urlStr := range c.urls {
u, err := url.Parse(urlStr)
if err == nil && u.User != nil {
c.basicAuth = true
c.basicAuthUsername = u.User.Username()
c.basicAuthPassword, _ = u.User.Password()
break
......@@ -490,7 +487,6 @@ func SetBasicAuth(username, password string) ClientOptionFunc {
return func(c *Client) error {
c.basicAuthUsername = username
c.basicAuthPassword = password
c.basicAuth = c.basicAuthUsername != "" || c.basicAuthPassword != ""
return nil
}
}
......@@ -506,6 +502,12 @@ func SetURL(urls ...string) ClientOptionFunc {
default:
c.urls = urls
}
// Check URLs
for _, urlStr := range c.urls {
if _, err := url.Parse(urlStr); err != nil {
return err
}
}
return nil
}
}
......@@ -962,7 +964,7 @@ func (c *Client) sniffNode(ctx context.Context, url string) []*conn {
}
c.mu.RLock()
if c.basicAuth {
if c.basicAuthUsername != "" || c.basicAuthPassword != "" {
req.SetBasicAuth(c.basicAuthUsername, c.basicAuthPassword)
}
c.mu.RUnlock()
......@@ -1076,7 +1078,8 @@ func (c *Client) healthcheck(parentCtx context.Context, timeout time.Duration, f
c.mu.RUnlock()
return
}
basicAuth := c.basicAuth
headers := c.headers
basicAuth := c.basicAuthUsername != "" || c.basicAuthPassword != ""
basicAuthUsername := c.basicAuthUsername
basicAuthPassword := c.basicAuthPassword
c.mu.RUnlock()
......@@ -1102,6 +1105,13 @@ func (c *Client) healthcheck(parentCtx context.Context, timeout time.Duration, f
if basicAuth {
req.SetBasicAuth(basicAuthUsername, basicAuthPassword)
}
if len(headers) > 0 {
for key, values := range headers {
for _, v := range values {
req.Header.Add(key, v)
}
}
}
res, err := c.c.Do((*http.Request)(req).WithContext(ctx))
if res != nil {
status = res.StatusCode
......@@ -1138,7 +1148,8 @@ func (c *Client) healthcheck(parentCtx context.Context, timeout time.Duration, f
func (c *Client) startupHealthcheck(parentCtx context.Context, timeout time.Duration) error {
c.mu.Lock()
urls := c.urls
basicAuth := c.basicAuth
headers := c.headers
basicAuth := c.basicAuthUsername != "" || c.basicAuthPassword != ""
basicAuthUsername := c.basicAuthUsername
basicAuthPassword := c.basicAuthPassword
c.mu.Unlock()
......@@ -1156,14 +1167,23 @@ func (c *Client) startupHealthcheck(parentCtx context.Context, timeout time.Dura
if basicAuth {
req.SetBasicAuth(basicAuthUsername, basicAuthPassword)
}
if len(headers) > 0 {
for key, values := range headers {
for _, v := range values {
req.Header.Add(key, v)
}
}
}
ctx, cancel := context.WithTimeout(parentCtx, timeout)
defer cancel()
req = req.WithContext(ctx)
res, err := c.c.Do(req)
if err == nil && res != nil && res.StatusCode >= 200 && res.StatusCode < 300 {
return nil
} else if err != nil {
if err != nil {
lastErr = err
} else if res.StatusCode >= 200 && res.StatusCode < 300 {
return nil
} else if res.StatusCode == http.StatusUnauthorized {
lastErr = &Error{Status: res.StatusCode}
}
}
select {
......@@ -1177,7 +1197,7 @@ func (c *Client) startupHealthcheck(parentCtx context.Context, timeout time.Dura
}
}
if lastErr != nil {
if IsContextErr(lastErr) {
if IsContextErr(lastErr) || IsUnauthorized(lastErr) {
return lastErr
}
return errors.Wrapf(ErrNoClient, "health check timeout: %v", lastErr)
......@@ -1264,7 +1284,7 @@ func (c *Client) PerformRequest(ctx context.Context, opt PerformRequestOptions)
c.mu.RLock()
timeout := c.healthcheckTimeout
basicAuth := c.basicAuth
basicAuth := c.basicAuthUsername != "" || c.basicAuthPassword != ""
basicAuthUsername := c.basicAuthUsername
basicAuthPassword := c.basicAuthPassword
sendGetBodyAs := c.sendGetBodyAs
......
......@@ -262,7 +262,7 @@ type clusterBlock struct {
type clusterStateMetadata struct {
ClusterUUID string `json:"cluster_uuid"`
ClusterUUIDCommitted string `json:"cluster_uuid_committed"`
ClusterUUIDCommitted bool `json:"cluster_uuid_committed"`
ClusterCoordination *clusterCoordinationMetaData `json:"cluster_coordination"`
Templates map[string]*indexTemplateMetaData `json:"templates"` // template name -> index template metadata
Indices map[string]*indexMetaData `json:"indices"` // index name _> meta data
......
......@@ -2,7 +2,7 @@ version: '3'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch-oss:7.6.2
image: docker.elastic.co/elasticsearch/elasticsearch-oss:7.8.0
hostname: elasticsearch
environment:
- cluster.name=elasticsearch
......@@ -28,7 +28,7 @@ services:
ports:
- 9200:9200
platinum:
image: docker.elastic.co/elasticsearch/elasticsearch:7.6.2
image: docker.elastic.co/elasticsearch/elasticsearch:7.8.0
hostname: elasticsearch-platinum
environment:
- cluster.name=platinum
......
......@@ -152,6 +152,15 @@ func IsConflict(err interface{}) bool {
return IsStatusCode(err, http.StatusConflict)
}
// IsUnauthorized returns true if the given error indicates that
// Elasticsearch returned HTTP status 401. This happens e.g. when the
// cluster is configured to require HTTP Basic Auth.
// The err parameter can be of type *elastic.Error, elastic.Error,
// *http.Response or int (indicating the HTTP status code).
func IsUnauthorized(err interface{}) bool {
return IsStatusCode(err, http.StatusUnauthorized)
}
// IsForbidden returns true if the given error indicates that Elasticsearch
// returned HTTP status 403. This happens e.g. due to a missing license.
// The err parameter can be of type *elastic.Error, elastic.Error,
......
......@@ -3,12 +3,14 @@ module github.com/olivere/elastic/v7
go 1.14
require (
github.com/aws/aws-sdk-go v1.30.7
github.com/aws/aws-sdk-go v1.33.5
github.com/fortytw2/leaktest v1.3.0
github.com/google/go-cmp v0.4.0
github.com/google/go-cmp v0.5.0
github.com/mailru/easyjson v0.7.1
github.com/opentracing/opentracing-go v1.1.0
github.com/opentracing/opentracing-go v1.2.0
github.com/pkg/errors v0.9.1
github.com/smartystreets/assertions v1.1.1 // indirect
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9
go.opencensus.io v0.22.3
github.com/smartystreets/gunit v1.3.4 // indirect
go.opencensus.io v0.22.4
)
......@@ -120,7 +120,7 @@ func (s *PingService) HttpHeadOnly(httpHeadOnly bool) *PingService {
// server, and an error.
func (s *PingService) Do(ctx context.Context) (*PingResult, int, error) {
s.client.mu.RLock()
basicAuth := s.client.basicAuth
basicAuth := s.client.basicAuthUsername != "" || s.client.basicAuthPassword != ""
basicAuthUsername := s.client.basicAuthUsername
basicAuthPassword := s.client.basicAuthPassword
defaultHeaders := s.client.headers
......
......@@ -294,6 +294,29 @@ func (s *ScrollService) MaxResponseSize(maxResponseSize int64) *ScrollService {
return s
}
// NoStoredFields indicates that no stored fields should be loaded, resulting in only
// id and type to be returned per field.
func (s *ScrollService) NoStoredFields() *ScrollService {
s.ss = s.ss.NoStoredFields()
return s
}
// StoredField adds a single field to load and return (note, must be stored) as
// part of the search request. If none are specified, the source of the
// document will be returned.
func (s *ScrollService) StoredField(fieldName string) *ScrollService {
s.ss = s.ss.StoredField(fieldName)
return s
}
// StoredFields sets the fields to load and return as part of the search request.
// If none are specified, the source of the document will be returned.
func (s *ScrollService) StoredFields(fields ...string) *ScrollService {
s.ss = s.ss.StoredFields(fields...)
return s
}
// ScrollId specifies the identifier of a scroll in action.
func (s *ScrollService) ScrollId(scrollId string) *ScrollService {
s.mu.Lock()
......
......@@ -19,6 +19,8 @@ import "errors"
type FiltersAggregation struct {
unnamedFilters []Query
namedFilters map[string]Query
otherBucket *bool
otherBucketKey string
subAggregations map[string]Aggregation
meta map[string]interface{}
}
......@@ -55,6 +57,20 @@ func (a *FiltersAggregation) FilterWithName(name string, filter Query) *FiltersA
return a
}
// OtherBucket indicates whether to include a bucket for documents not
// matching any filter.
func (a *FiltersAggregation) OtherBucket(otherBucket bool) *FiltersAggregation {
a.otherBucket = &otherBucket
return a
}
// OtherBucketKey sets the key to use for the bucket for documents not
// matching any filter.
func (a *FiltersAggregation) OtherBucketKey(key string) *FiltersAggregation {
a.otherBucketKey = key
return a
}
// SubAggregation adds a sub-aggregation to this aggregation.
func (a *FiltersAggregation) SubAggregation(name string, subAggregation Aggregation) *FiltersAggregation {
a.subAggregations[name] = subAggregation
......@@ -116,6 +132,13 @@ func (a *FiltersAggregation) Source() (interface{}, error) {
filters["filters"] = dict
}
if v := a.otherBucket; v != nil {
filters["other_bucket"] = *v
}
if v := a.otherBucketKey; v != "" {
filters["other_bucket_key"] = v
}
// AggregationBuilder (SubAggregations)
if len(a.subAggregations) > 0 {
aggsMap := make(map[string]interface{})
......
......@@ -39,7 +39,6 @@ type MultiMatchQuery struct {
func NewMultiMatchQuery(text interface{}, fields ...string) *MultiMatchQuery {
q := &MultiMatchQuery{
text: text,
fields: make([]string, 0),
fieldBoosts: make(map[string]*float64),
}
q.fields = append(q.fields, fields...)
......@@ -68,22 +67,34 @@ func (q *MultiMatchQuery) Type(typ string) *MultiMatchQuery {
switch strings.ToLower(typ) {
default: // best_fields / boolean
q.typ = "best_fields"
q.tieBreaker = &zero
if q.tieBreaker == nil {
q.tieBreaker = &zero
}
case "most_fields":
q.typ = "most_fields"
q.tieBreaker = &one
if q.tieBreaker == nil {
q.tieBreaker = &one
}
case "cross_fields":
q.typ = "cross_fields"
q.tieBreaker = &zero
if q.tieBreaker == nil {
q.tieBreaker = &zero
}
case "phrase":
q.typ = "phrase"
q.tieBreaker = &zero
if q.tieBreaker == nil {
q.tieBreaker = &zero
}
case "phrase_prefix":
q.typ = "phrase_prefix"
q.tieBreaker = &zero
if q.tieBreaker == nil {
q.tieBreaker = &zero
}
case "bool_prefix":
q.typ = "bool_prefix"
q.tieBreaker = &zero
if q.tieBreaker == nil {
q.tieBreaker = &zero
}
}
return q
}
......@@ -209,19 +220,21 @@ func (q *MultiMatchQuery) Source() (interface{}, error) {
multiMatch["query"] = q.text
if len(q.fields) > 0 {
var fields []string
for _, field := range q.fields {
if boost, found := q.fieldBoosts[field]; found {
if boost != nil {
fields = append(fields, fmt.Sprintf("%s^%f", field, *boost))
} else {
fields = append(fields, field)
}
var fields []string
for _, field := range q.fields {
if boost, found := q.fieldBoosts[field]; found {
if boost != nil {
fields = append(fields, fmt.Sprintf("%s^%f", field, *boost))
} else {
fields = append(fields, field)
}
} else {
fields = append(fields, field)
}
}
if fields == nil {
multiMatch["fields"] = []string{}
} else {
multiMatch["fields"] = fields
}
......
// Copyright 2012-present Oliver Eilhard. All rights reserved.
// Use of this source code is governed by a MIT-license.
// See http://olivere.mit-license.org/license.txt for details.
package elastic
// SpanFirstQuery spans near the beginning of a field.
// The span first query maps to Lucene SpanFirstQuery
//
// See https://www.elastic.co/guide/en/elasticsearch/reference/7.7/query-dsl-span-first-query.html
// for details.
type SpanFirstQuery struct {
match Query
end int
boost *float64
queryName string
}
// NewSpanFirstQuery creates a new SpanFirstQuery.
func NewSpanFirstQuery(query Query, end int) *SpanFirstQuery {
return &SpanFirstQuery{
match: query,
end: end,
}
}
// Match sets the query, e.g. a SpanTermQuery.
func (q *SpanFirstQuery) Match(query Query) *SpanFirstQuery {
q.match = query
return q
}
// End specifies the maximum end position of the match, which needs to be positive.
func (q *SpanFirstQuery) End(end int) *SpanFirstQuery {
q.end = end
return q
}
// Boost sets the boost for this query.
func (q *SpanFirstQuery) Boost(boost float64) *SpanFirstQuery {
q.boost = &boost
return q
}
// QueryName sets the query name for the filter that can be used when
// searching for matched_filters per hit.
func (q *SpanFirstQuery) QueryName(queryName string) *SpanFirstQuery {
q.queryName = queryName
return q
}
// Source returns the JSON body.
func (q *SpanFirstQuery) Source() (interface{}, error) {
m := make(map[string]interface{})
c := make(map[string]interface{})
if v := q.match; v != nil {
src, err := q.match.Source()
if err != nil {
return nil, err
}
c["match"] = src
}
c["end"] = q.end