summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/blevesearch/bleve/search
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/blevesearch/bleve/search')
-rw-r--r--vendor/github.com/blevesearch/bleve/search/collector/heap.go30
-rw-r--r--vendor/github.com/blevesearch/bleve/search/collector/list.go15
-rw-r--r--vendor/github.com/blevesearch/bleve/search/collector/slice.go15
-rw-r--r--vendor/github.com/blevesearch/bleve/search/collector/topn.go83
-rw-r--r--vendor/github.com/blevesearch/bleve/search/facet/facet_builder_datetime.go53
-rw-r--r--vendor/github.com/blevesearch/bleve/search/facet/facet_builder_numeric.go53
-rw-r--r--vendor/github.com/blevesearch/bleve/search/facet/facet_builder_terms.go29
-rw-r--r--vendor/github.com/blevesearch/bleve/search/facets_builder.go41
-rw-r--r--vendor/github.com/blevesearch/bleve/search/highlight/format/html/html.go2
-rw-r--r--vendor/github.com/blevesearch/bleve/search/highlight/highlighter/simple/fragment_scorer_simple.go2
-rw-r--r--vendor/github.com/blevesearch/bleve/search/highlight/highlighter/simple/highlighter_simple.go2
-rw-r--r--vendor/github.com/blevesearch/bleve/search/highlight/term_locations.go14
-rw-r--r--vendor/github.com/blevesearch/bleve/search/pool.go12
-rw-r--r--vendor/github.com/blevesearch/bleve/search/query/bool_field.go13
-rw-r--r--vendor/github.com/blevesearch/bleve/search/query/boolean.go69
-rw-r--r--vendor/github.com/blevesearch/bleve/search/query/conjunction.go26
-rw-r--r--vendor/github.com/blevesearch/bleve/search/query/date_range.go9
-rw-r--r--vendor/github.com/blevesearch/bleve/search/query/disjunction.go29
-rw-r--r--vendor/github.com/blevesearch/bleve/search/query/docid.go6
-rw-r--r--vendor/github.com/blevesearch/bleve/search/query/fuzzy.go8
-rw-r--r--vendor/github.com/blevesearch/bleve/search/query/geo_boundingbox.go113
-rw-r--r--vendor/github.com/blevesearch/bleve/search/query/geo_distance.go100
-rw-r--r--vendor/github.com/blevesearch/bleve/search/query/match.go12
-rw-r--r--vendor/github.com/blevesearch/bleve/search/query/match_all.go8
-rw-r--r--vendor/github.com/blevesearch/bleve/search/query/match_none.go4
-rw-r--r--vendor/github.com/blevesearch/bleve/search/query/match_phrase.go21
-rw-r--r--vendor/github.com/blevesearch/bleve/search/query/multi_phrase.go80
-rw-r--r--vendor/github.com/blevesearch/bleve/search/query/numeric_range.go8
-rw-r--r--vendor/github.com/blevesearch/bleve/search/query/phrase.go38
-rw-r--r--vendor/github.com/blevesearch/bleve/search/query/prefix.go8
-rw-r--r--vendor/github.com/blevesearch/bleve/search/query/query.go52
-rw-r--r--vendor/github.com/blevesearch/bleve/search/query/query_string.go10
-rw-r--r--vendor/github.com/blevesearch/bleve/search/query/query_string.y63
-rw-r--r--vendor/github.com/blevesearch/bleve/search/query/query_string.y.go148
-rw-r--r--vendor/github.com/blevesearch/bleve/search/query/query_string_parser.go10
-rw-r--r--vendor/github.com/blevesearch/bleve/search/query/regexp.go24
-rw-r--r--vendor/github.com/blevesearch/bleve/search/query/term.go8
-rw-r--r--vendor/github.com/blevesearch/bleve/search/query/term_range.go95
-rw-r--r--vendor/github.com/blevesearch/bleve/search/query/wildcard.go10
-rw-r--r--vendor/github.com/blevesearch/bleve/search/scorer/scorer_conjunction.go12
-rw-r--r--vendor/github.com/blevesearch/bleve/search/scorer/scorer_constant.go14
-rw-r--r--vendor/github.com/blevesearch/bleve/search/scorer/scorer_disjunction.go14
-rw-r--r--vendor/github.com/blevesearch/bleve/search/scorer/scorer_term.go56
-rw-r--r--vendor/github.com/blevesearch/bleve/search/search.go38
-rw-r--r--vendor/github.com/blevesearch/bleve/search/searcher/search_boolean.go4
-rw-r--r--vendor/github.com/blevesearch/bleve/search/searcher/search_conjunction.go8
-rw-r--r--vendor/github.com/blevesearch/bleve/search/searcher/search_disjunction.go25
-rw-r--r--vendor/github.com/blevesearch/bleve/search/searcher/search_docid.go4
-rw-r--r--vendor/github.com/blevesearch/bleve/search/searcher/search_filter.go88
-rw-r--r--vendor/github.com/blevesearch/bleve/search/searcher/search_fuzzy.go87
-rw-r--r--vendor/github.com/blevesearch/bleve/search/searcher/search_geoboundingbox.go173
-rw-r--r--vendor/github.com/blevesearch/bleve/search/searcher/search_geopointdistance.go117
-rw-r--r--vendor/github.com/blevesearch/bleve/search/searcher/search_match_all.go4
-rw-r--r--vendor/github.com/blevesearch/bleve/search/searcher/search_multi_term.go85
-rw-r--r--vendor/github.com/blevesearch/bleve/search/searcher/search_numeric_range.go108
-rw-r--r--vendor/github.com/blevesearch/bleve/search/searcher/search_phrase.go250
-rw-r--r--vendor/github.com/blevesearch/bleve/search/searcher/search_regexp.go44
-rw-r--r--vendor/github.com/blevesearch/bleve/search/searcher/search_term.go30
-rw-r--r--vendor/github.com/blevesearch/bleve/search/searcher/search_term_prefix.go84
-rw-r--r--vendor/github.com/blevesearch/bleve/search/searcher/search_term_range.go79
-rw-r--r--vendor/github.com/blevesearch/bleve/search/sort.go224
61 files changed, 2099 insertions, 772 deletions
diff --git a/vendor/github.com/blevesearch/bleve/search/collector/heap.go b/vendor/github.com/blevesearch/bleve/search/collector/heap.go
index 19f3a05982..bdf72eade3 100644
--- a/vendor/github.com/blevesearch/bleve/search/collector/heap.go
+++ b/vendor/github.com/blevesearch/bleve/search/collector/heap.go
@@ -34,11 +34,20 @@ func newStoreHeap(cap int, compare collectorCompare) *collectStoreHeap {
return rv
}
-func (c *collectStoreHeap) Add(doc *search.DocumentMatch) {
+func (c *collectStoreHeap) AddNotExceedingSize(doc *search.DocumentMatch,
+ size int) *search.DocumentMatch {
+ c.add(doc)
+ if c.Len() > size {
+ return c.removeLast()
+ }
+ return nil
+}
+
+func (c *collectStoreHeap) add(doc *search.DocumentMatch) {
heap.Push(c, doc)
}
-func (c *collectStoreHeap) RemoveLast() *search.DocumentMatch {
+func (c *collectStoreHeap) removeLast() *search.DocumentMatch {
return heap.Pop(c).(*search.DocumentMatch)
}
@@ -49,17 +58,12 @@ func (c *collectStoreHeap) Final(skip int, fixup collectorFixup) (search.Documen
return make(search.DocumentMatchCollection, 0), nil
}
rv := make(search.DocumentMatchCollection, size)
- for count > 0 {
- count--
-
- if count >= skip {
- size--
- doc := heap.Pop(c).(*search.DocumentMatch)
- rv[size] = doc
- err := fixup(doc)
- if err != nil {
- return nil, err
- }
+ for i := size - 1; i >= 0; i-- {
+ doc := heap.Pop(c).(*search.DocumentMatch)
+ rv[i] = doc
+ err := fixup(doc)
+ if err != nil {
+ return nil, err
}
}
return rv, nil
diff --git a/vendor/github.com/blevesearch/bleve/search/collector/list.go b/vendor/github.com/blevesearch/bleve/search/collector/list.go
index 51b47b12da..ec2f69cb82 100644
--- a/vendor/github.com/blevesearch/bleve/search/collector/list.go
+++ b/vendor/github.com/blevesearch/bleve/search/collector/list.go
@@ -34,7 +34,16 @@ func newStoreList(cap int, compare collectorCompare) *collectStoreList {
return rv
}
-func (c *collectStoreList) Add(doc *search.DocumentMatch) {
+func (c *collectStoreList) AddNotExceedingSize(doc *search.DocumentMatch,
+ size int) *search.DocumentMatch {
+ c.add(doc)
+ if c.len() > size {
+ return c.removeLast()
+ }
+ return nil
+}
+
+func (c *collectStoreList) add(doc *search.DocumentMatch) {
for e := c.results.Front(); e != nil; e = e.Next() {
curr := e.Value.(*search.DocumentMatch)
if c.compare(doc, curr) >= 0 {
@@ -46,7 +55,7 @@ func (c *collectStoreList) Add(doc *search.DocumentMatch) {
c.results.PushBack(doc)
}
-func (c *collectStoreList) RemoveLast() *search.DocumentMatch {
+func (c *collectStoreList) removeLast() *search.DocumentMatch {
return c.results.Remove(c.results.Front()).(*search.DocumentMatch)
}
@@ -73,6 +82,6 @@ func (c *collectStoreList) Final(skip int, fixup collectorFixup) (search.Documen
return search.DocumentMatchCollection{}, nil
}
-func (c *collectStoreList) Len() int {
+func (c *collectStoreList) len() int {
return c.results.Len()
}
diff --git a/vendor/github.com/blevesearch/bleve/search/collector/slice.go b/vendor/github.com/blevesearch/bleve/search/collector/slice.go
index b061643ee4..32cb862447 100644
--- a/vendor/github.com/blevesearch/bleve/search/collector/slice.go
+++ b/vendor/github.com/blevesearch/bleve/search/collector/slice.go
@@ -29,7 +29,16 @@ func newStoreSlice(cap int, compare collectorCompare) *collectStoreSlice {
return rv
}
-func (c *collectStoreSlice) Add(doc *search.DocumentMatch) {
+func (c *collectStoreSlice) AddNotExceedingSize(doc *search.DocumentMatch,
+ size int) *search.DocumentMatch {
+ c.add(doc)
+ if c.len() > size {
+ return c.removeLast()
+ }
+ return nil
+}
+
+func (c *collectStoreSlice) add(doc *search.DocumentMatch) {
// find where to insert, starting at end (lowest)
i := len(c.slice)
for ; i > 0; i-- {
@@ -44,7 +53,7 @@ func (c *collectStoreSlice) Add(doc *search.DocumentMatch) {
c.slice[i] = doc
}
-func (c *collectStoreSlice) RemoveLast() *search.DocumentMatch {
+func (c *collectStoreSlice) removeLast() *search.DocumentMatch {
var rv *search.DocumentMatch
rv, c.slice = c.slice[len(c.slice)-1], c.slice[:len(c.slice)-1]
return rv
@@ -63,6 +72,6 @@ func (c *collectStoreSlice) Final(skip int, fixup collectorFixup) (search.Docume
return search.DocumentMatchCollection{}, nil
}
-func (c *collectStoreSlice) Len() int {
+func (c *collectStoreSlice) len() int {
return len(c.slice)
}
diff --git a/vendor/github.com/blevesearch/bleve/search/collector/topn.go b/vendor/github.com/blevesearch/bleve/search/collector/topn.go
index 152d92f732..2c7c6752df 100644
--- a/vendor/github.com/blevesearch/bleve/search/collector/topn.go
+++ b/vendor/github.com/blevesearch/bleve/search/collector/topn.go
@@ -22,6 +22,15 @@ import (
"golang.org/x/net/context"
)
+type collectorStore interface {
+ // Add the document, and if the new store size exceeds the provided size
+ // the last element is removed and returned. If the size has not been
+ // exceeded, nil is returned.
+ AddNotExceedingSize(doc *search.DocumentMatch, size int) *search.DocumentMatch
+
+ Final(skip int, fixup collectorFixup) (search.DocumentMatchCollection, error)
+}
+
// PreAllocSizeSkipCap will cap preallocation to this amount when
// size+skip exceeds this value
var PreAllocSizeSkipCap = 1000
@@ -41,7 +50,7 @@ type TopNCollector struct {
results search.DocumentMatchCollection
facetsBuilder *search.FacetsBuilder
- store *collectStoreSlice
+ store collectorStore
needDocIds bool
neededFields []string
@@ -68,9 +77,15 @@ func NewTopNCollector(size int, skip int, sort search.SortOrder) *TopNCollector
backingSize = PreAllocSizeSkipCap + 1
}
- hc.store = newStoreSlice(backingSize, func(i, j *search.DocumentMatch) int {
- return hc.sort.Compare(hc.cachedScoring, hc.cachedDesc, i, j)
- })
+ if size+skip > 10 {
+ hc.store = newStoreHeap(backingSize, func(i, j *search.DocumentMatch) int {
+ return hc.sort.Compare(hc.cachedScoring, hc.cachedDesc, i, j)
+ })
+ } else {
+ hc.store = newStoreSlice(backingSize, func(i, j *search.DocumentMatch) int {
+ return hc.sort.Compare(hc.cachedScoring, hc.cachedDesc, i, j)
+ })
+ }
// these lookups traverse an interface, so do once up-front
if sort.RequiresDocID() {
@@ -114,12 +129,6 @@ func (hc *TopNCollector) Collect(ctx context.Context, searcher search.Searcher,
default:
}
}
- if hc.facetsBuilder != nil {
- err = hc.facetsBuilder.Update(next)
- if err != nil {
- break
- }
- }
err = hc.collectSingle(searchContext, reader, next)
if err != nil {
@@ -144,6 +153,16 @@ func (hc *TopNCollector) Collect(ctx context.Context, searcher search.Searcher,
var sortByScoreOpt = []string{"_score"}
func (hc *TopNCollector) collectSingle(ctx *search.SearchContext, reader index.IndexReader, d *search.DocumentMatch) error {
+ var err error
+
+ // visit field terms for features that require it (sort, facets)
+ if len(hc.neededFields) > 0 {
+ err = hc.visitFieldTerms(reader, d)
+ if err != nil {
+ return err
+ }
+ }
+
// increment total hits
hc.total++
d.HitNumber = hc.total
@@ -153,7 +172,6 @@ func (hc *TopNCollector) collectSingle(ctx *search.SearchContext, reader index.I
hc.maxScore = d.Score
}
- var err error
// see if we need to load ID (at this early stage, for example to sort on it)
if hc.needDocIds {
d.ID, err = reader.ExternalID(d.IndexInternalID)
@@ -162,22 +180,6 @@ func (hc *TopNCollector) collectSingle(ctx *search.SearchContext, reader index.I
}
}
- // see if we need to load the stored fields
- if len(hc.neededFields) > 0 {
- // find out which fields haven't been loaded yet
- fieldsToLoad := d.CachedFieldTerms.FieldsNotYetCached(hc.neededFields)
- // look them up
- fieldTerms, err := reader.DocumentFieldTerms(d.IndexInternalID, fieldsToLoad)
- if err != nil {
- return err
- }
- // cache these as well
- if d.CachedFieldTerms == nil {
- d.CachedFieldTerms = make(map[string][]string)
- }
- d.CachedFieldTerms.Merge(fieldTerms)
- }
-
// compute this hits sort value
if len(hc.sort) == 1 && hc.cachedScoring[0] {
d.Sort = sortByScoreOpt
@@ -197,9 +199,8 @@ func (hc *TopNCollector) collectSingle(ctx *search.SearchContext, reader index.I
}
}
- hc.store.Add(d)
- if hc.store.Len() > hc.size+hc.skip {
- removed := hc.store.RemoveLast()
+ removed := hc.store.AddNotExceedingSize(d, hc.size+hc.skip)
+ if removed != nil {
if hc.lowestMatchOutsideResults == nil {
hc.lowestMatchOutsideResults = removed
} else {
@@ -215,9 +216,31 @@ func (hc *TopNCollector) collectSingle(ctx *search.SearchContext, reader index.I
return nil
}
+// visitFieldTerms is responsible for visiting the field terms of the
+// search hit, and passing visited terms to the sort and facet builder
+func (hc *TopNCollector) visitFieldTerms(reader index.IndexReader, d *search.DocumentMatch) error {
+ if hc.facetsBuilder != nil {
+ hc.facetsBuilder.StartDoc()
+ }
+
+ err := reader.DocumentVisitFieldTerms(d.IndexInternalID, hc.neededFields, func(field string, term []byte) {
+ if hc.facetsBuilder != nil {
+ hc.facetsBuilder.UpdateVisitor(field, term)
+ }
+ hc.sort.UpdateVisitor(field, term)
+ })
+
+ if hc.facetsBuilder != nil {
+ hc.facetsBuilder.EndDoc()
+ }
+
+ return err
+}
+
// SetFacetsBuilder registers a facet builder for this collector
func (hc *TopNCollector) SetFacetsBuilder(facetsBuilder *search.FacetsBuilder) {
hc.facetsBuilder = facetsBuilder
+ hc.neededFields = append(hc.neededFields, hc.facetsBuilder.RequiredFields()...)
}
// finalizeResults starts with the heap containing the final top size+skip
diff --git a/vendor/github.com/blevesearch/bleve/search/facet/facet_builder_datetime.go b/vendor/github.com/blevesearch/bleve/search/facet/facet_builder_datetime.go
index c3184ac6e3..8657a553a9 100644
--- a/vendor/github.com/blevesearch/bleve/search/facet/facet_builder_datetime.go
+++ b/vendor/github.com/blevesearch/bleve/search/facet/facet_builder_datetime.go
@@ -18,7 +18,6 @@ import (
"sort"
"time"
- "github.com/blevesearch/bleve/index"
"github.com/blevesearch/bleve/numeric"
"github.com/blevesearch/bleve/search"
)
@@ -35,6 +34,7 @@ type DateTimeFacetBuilder struct {
total int
missing int
ranges map[string]*dateTimeRange
+ sawValue bool
}
func NewDateTimeFacetBuilder(field string, size int) *DateTimeFacetBuilder {
@@ -58,36 +58,35 @@ func (fb *DateTimeFacetBuilder) Field() string {
return fb.field
}
-func (fb *DateTimeFacetBuilder) Update(ft index.FieldTerms) {
- terms, ok := ft[fb.field]
- if ok {
- for _, term := range terms {
- // only consider the values which are shifted 0
- prefixCoded := numeric.PrefixCoded(term)
- shift, err := prefixCoded.Shift()
- if err == nil && shift == 0 {
- i64, err := prefixCoded.Int64()
- if err == nil {
- t := time.Unix(0, i64)
-
- // look at each of the ranges for a match
- for rangeName, r := range fb.ranges {
-
- if (r.start.IsZero() || t.After(r.start) || t.Equal(r.start)) && (r.end.IsZero() || t.Before(r.end)) {
-
- existingCount, existed := fb.termsCount[rangeName]
- if existed {
- fb.termsCount[rangeName] = existingCount + 1
- } else {
- fb.termsCount[rangeName] = 1
- }
- fb.total++
- }
+func (fb *DateTimeFacetBuilder) UpdateVisitor(field string, term []byte) {
+ if field == fb.field {
+ fb.sawValue = true
+ // only consider the values which are shifted 0
+ prefixCoded := numeric.PrefixCoded(term)
+ shift, err := prefixCoded.Shift()
+ if err == nil && shift == 0 {
+ i64, err := prefixCoded.Int64()
+ if err == nil {
+ t := time.Unix(0, i64)
+
+ // look at each of the ranges for a match
+ for rangeName, r := range fb.ranges {
+ if (r.start.IsZero() || t.After(r.start) || t.Equal(r.start)) && (r.end.IsZero() || t.Before(r.end)) {
+ fb.termsCount[rangeName] = fb.termsCount[rangeName] + 1
+ fb.total++
}
}
}
}
- } else {
+ }
+}
+
+func (fb *DateTimeFacetBuilder) StartDoc() {
+ fb.sawValue = false
+}
+
+func (fb *DateTimeFacetBuilder) EndDoc() {
+ if !fb.sawValue {
fb.missing++
}
}
diff --git a/vendor/github.com/blevesearch/bleve/search/facet/facet_builder_numeric.go b/vendor/github.com/blevesearch/bleve/search/facet/facet_builder_numeric.go
index 19beb3c2d9..2ab5f27893 100644
--- a/vendor/github.com/blevesearch/bleve/search/facet/facet_builder_numeric.go
+++ b/vendor/github.com/blevesearch/bleve/search/facet/facet_builder_numeric.go
@@ -17,7 +17,6 @@ package facet
import (
"sort"
- "github.com/blevesearch/bleve/index"
"github.com/blevesearch/bleve/numeric"
"github.com/blevesearch/bleve/search"
)
@@ -34,6 +33,7 @@ type NumericFacetBuilder struct {
total int
missing int
ranges map[string]*numericRange
+ sawValue bool
}
func NewNumericFacetBuilder(field string, size int) *NumericFacetBuilder {
@@ -57,36 +57,35 @@ func (fb *NumericFacetBuilder) Field() string {
return fb.field
}
-func (fb *NumericFacetBuilder) Update(ft index.FieldTerms) {
- terms, ok := ft[fb.field]
- if ok {
- for _, term := range terms {
- // only consider the values which are shifted 0
- prefixCoded := numeric.PrefixCoded(term)
- shift, err := prefixCoded.Shift()
- if err == nil && shift == 0 {
- i64, err := prefixCoded.Int64()
- if err == nil {
- f64 := numeric.Int64ToFloat64(i64)
-
- // look at each of the ranges for a match
- for rangeName, r := range fb.ranges {
-
- if (r.min == nil || f64 >= *r.min) && (r.max == nil || f64 < *r.max) {
-
- existingCount, existed := fb.termsCount[rangeName]
- if existed {
- fb.termsCount[rangeName] = existingCount + 1
- } else {
- fb.termsCount[rangeName] = 1
- }
- fb.total++
- }
+func (fb *NumericFacetBuilder) UpdateVisitor(field string, term []byte) {
+ if field == fb.field {
+ fb.sawValue = true
+ // only consider the values which are shifted 0
+ prefixCoded := numeric.PrefixCoded(term)
+ shift, err := prefixCoded.Shift()
+ if err == nil && shift == 0 {
+ i64, err := prefixCoded.Int64()
+ if err == nil {
+ f64 := numeric.Int64ToFloat64(i64)
+
+ // look at each of the ranges for a match
+ for rangeName, r := range fb.ranges {
+ if (r.min == nil || f64 >= *r.min) && (r.max == nil || f64 < *r.max) {
+ fb.termsCount[rangeName] = fb.termsCount[rangeName] + 1
+ fb.total++
}
}
}
}
- } else {
+ }
+}
+
+func (fb *NumericFacetBuilder) StartDoc() {
+ fb.sawValue = false
+}
+
+func (fb *NumericFacetBuilder) EndDoc() {
+ if !fb.sawValue {
fb.missing++
}
}
diff --git a/vendor/github.com/blevesearch/bleve/search/facet/facet_builder_terms.go b/vendor/github.com/blevesearch/bleve/search/facet/facet_builder_terms.go
index 1664af24bc..a41e475a91 100644
--- a/vendor/github.com/blevesearch/bleve/search/facet/facet_builder_terms.go
+++ b/vendor/github.com/blevesearch/bleve/search/facet/facet_builder_terms.go
@@ -17,7 +17,6 @@ package facet
import (
"sort"
- "github.com/blevesearch/bleve/index"
"github.com/blevesearch/bleve/search"
)
@@ -27,6 +26,7 @@ type TermsFacetBuilder struct {
termsCount map[string]int
total int
missing int
+ sawValue bool
}
func NewTermsFacetBuilder(field string, size int) *TermsFacetBuilder {
@@ -41,19 +41,20 @@ func (fb *TermsFacetBuilder) Field() string {
return fb.field
}
-func (fb *TermsFacetBuilder) Update(ft index.FieldTerms) {
- terms, ok := ft[fb.field]
- if ok {
- for _, term := range terms {
- existingCount, existed := fb.termsCount[term]
- if existed {
- fb.termsCount[term] = existingCount + 1
- } else {
- fb.termsCount[term] = 1
- }
- fb.total++
- }
- } else {
+func (fb *TermsFacetBuilder) UpdateVisitor(field string, term []byte) {
+ if field == fb.field {
+ fb.sawValue = true
+ fb.termsCount[string(term)] = fb.termsCount[string(term)] + 1
+ fb.total++
+ }
+}
+
+func (fb *TermsFacetBuilder) StartDoc() {
+ fb.sawValue = false
+}
+
+func (fb *TermsFacetBuilder) EndDoc() {
+ if !fb.sawValue {
fb.missing++
}
}
diff --git a/vendor/github.com/blevesearch/bleve/search/facets_builder.go b/vendor/github.com/blevesearch/bleve/search/facets_builder.go
index 2cb6e5c897..05e270413a 100644
--- a/vendor/github.com/blevesearch/bleve/search/facets_builder.go
+++ b/vendor/github.com/blevesearch/bleve/search/facets_builder.go
@@ -21,7 +21,10 @@ import (
)
type FacetBuilder interface {
- Update(index.FieldTerms)
+ StartDoc()
+ UpdateVisitor(field string, term []byte)
+ EndDoc()
+
Result() *FacetResult
Field() string
}
@@ -41,33 +44,29 @@ func NewFacetsBuilder(indexReader index.IndexReader) *FacetsBuilder {
func (fb *FacetsBuilder) Add(name string, facetBuilder FacetBuilder) {
fb.facets[name] = facetBuilder
+ fb.fields = append(fb.fields, facetBuilder.Field())
}
-func (fb *FacetsBuilder) Update(docMatch *DocumentMatch) error {
- if fb.fields == nil {
- for _, facetBuilder := range fb.facets {
- fb.fields = append(fb.fields, facetBuilder.Field())
- }
+func (fb *FacetsBuilder) RequiredFields() []string {
+ return fb.fields
+}
+
+func (fb *FacetsBuilder) StartDoc() {
+ for _, facetBuilder := range fb.facets {
+ facetBuilder.StartDoc()
}
+}
- if len(fb.fields) > 0 {
- // find out which fields haven't been loaded yet
- fieldsToLoad := docMatch.CachedFieldTerms.FieldsNotYetCached(fb.fields)
- // look them up
- fieldTerms, err := fb.indexReader.DocumentFieldTerms(docMatch.IndexInternalID, fieldsToLoad)
- if err != nil {
- return err
- }
- // cache these as well
- if docMatch.CachedFieldTerms == nil {
- docMatch.CachedFieldTerms = make(map[string][]string)
- }
- docMatch.CachedFieldTerms.Merge(fieldTerms)
+func (fb *FacetsBuilder) EndDoc() {
+ for _, facetBuilder := range fb.facets {
+ facetBuilder.EndDoc()
}
+}
+
+func (fb *FacetsBuilder) UpdateVisitor(field string, term []byte) {
for _, facetBuilder := range fb.facets {
- facetBuilder.Update(docMatch.CachedFieldTerms)
+ facetBuilder.UpdateVisitor(field, term)
}
- return nil
}
type TermFacet struct {
diff --git a/vendor/github.com/blevesearch/bleve/search/highlight/format/html/html.go b/vendor/github.com/blevesearch/bleve/search/highlight/format/html/html.go
index 2ff4e9ba60..8154e790b0 100644
--- a/vendor/github.com/blevesearch/bleve/search/highlight/format/html/html.go
+++ b/vendor/github.com/blevesearch/bleve/search/highlight/format/html/html.go
@@ -44,7 +44,7 @@ func (a *FragmentFormatter) Format(f *highlight.Fragment, orderedTermLocations h
continue
}
// make sure the array positions match
- if !highlight.SameArrayPositions(f.ArrayPositions, termLocation.ArrayPositions) {
+ if !termLocation.ArrayPositions.Equals(f.ArrayPositions) {
continue
}
if termLocation.Start < curr {
diff --git a/vendor/github.com/blevesearch/bleve/search/highlight/highlighter/simple/fragment_scorer_simple.go b/vendor/github.com/blevesearch/bleve/search/highlight/highlighter/simple/fragment_scorer_simple.go
index 2a6ce68f48..3ec4c3d28e 100644
--- a/vendor/github.com/blevesearch/bleve/search/highlight/highlighter/simple/fragment_scorer_simple.go
+++ b/vendor/github.com/blevesearch/bleve/search/highlight/highlighter/simple/fragment_scorer_simple.go
@@ -37,7 +37,7 @@ func (s *FragmentScorer) Score(f *highlight.Fragment) {
OUTER:
for _, locations := range s.tlm {
for _, location := range locations {
- if highlight.SameArrayPositions(f.ArrayPositions, location.ArrayPositions) && int(location.Start) >= f.Start && int(location.End) <= f.End {
+ if location.ArrayPositions.Equals(f.ArrayPositions) && int(location.Start) >= f.Start && int(location.End) <= f.End {
score += 1.0
// once we find a term in the fragment
// don't care about additional matches
diff --git a/vendor/github.com/blevesearch/bleve/search/highlight/highlighter/simple/highlighter_simple.go b/vendor/github.com/blevesearch/bleve/search/highlight/highlighter/simple/highlighter_simple.go
index 3815c8e12d..4849516bad 100644
--- a/vendor/github.com/blevesearch/bleve/search/highlight/highlighter/simple/highlighter_simple.go
+++ b/vendor/github.com/blevesearch/bleve/search/highlight/highlighter/simple/highlighter_simple.go
@@ -87,7 +87,7 @@ func (s *Highlighter) BestFragmentsInField(dm *search.DocumentMatch, doc *docume
if ok {
termLocationsSameArrayPosition := make(highlight.TermLocations, 0)
for _, otl := range orderedTermLocations {
- if highlight.SameArrayPositions(f.ArrayPositions(), otl.ArrayPositions) {
+ if otl.ArrayPositions.Equals(f.ArrayPositions()) {
termLocationsSameArrayPosition = append(termLocationsSameArrayPosition, otl)
}
}
diff --git a/vendor/github.com/blevesearch/bleve/search/highlight/term_locations.go b/vendor/github.com/blevesearch/bleve/search/highlight/term_locations.go
index c53c2dba38..6d2cb133ee 100644
--- a/vendor/github.com/blevesearch/bleve/search/highlight/term_locations.go
+++ b/vendor/github.com/blevesearch/bleve/search/highlight/term_locations.go
@@ -23,7 +23,7 @@ import (
type TermLocation struct {
Term string
- ArrayPositions []float64
+ ArrayPositions search.ArrayPositions
Pos int
Start int
End int
@@ -103,15 +103,3 @@ func OrderTermLocations(tlm search.TermLocationMap) TermLocations {
sort.Sort(rv)
return rv
}
-
-func SameArrayPositions(fieldArrayPositions []uint64, termLocationArrayPositions []float64) bool {
- if len(fieldArrayPositions) != len(termLocationArrayPositions) {
- return false
- }
- for i := 0; i < len(fieldArrayPositions); i++ {
- if fieldArrayPositions[i] != uint64(termLocationArrayPositions[i]) {
- return false
- }
- }
- return true
-}
diff --git a/vendor/github.com/blevesearch/bleve/search/pool.go b/vendor/github.com/blevesearch/bleve/search/pool.go
index 043e53f82f..b9b52a613f 100644
--- a/vendor/github.com/blevesearch/bleve/search/pool.go
+++ b/vendor/github.com/blevesearch/bleve/search/pool.go
@@ -37,13 +37,17 @@ func defaultDocumentMatchPoolTooSmall(p *DocumentMatchPool) *DocumentMatch {
// pre-allocated to accommodate the requested number of DocumentMatch
// instances
func NewDocumentMatchPool(size, sortsize int) *DocumentMatchPool {
- avail := make(DocumentMatchCollection, 0, size)
+ avail := make(DocumentMatchCollection, size)
// pre-allocate the expected number of instances
startBlock := make([]DocumentMatch, size)
+ startSorts := make([]string, size*sortsize)
// make these initial instances available
- for i := range startBlock {
- startBlock[i].Sort = make([]string, 0, sortsize)
- avail = append(avail, &startBlock[i])
+ i, j := 0, 0
+ for i < size {
+ avail[i] = &startBlock[i]
+ avail[i].Sort = startSorts[j:j]
+ i += 1
+ j += sortsize
}
return &DocumentMatchPool{
avail: avail,
diff --git a/vendor/github.com/blevesearch/bleve/search/query/bool_field.go b/vendor/github.com/blevesearch/bleve/search/query/bool_field.go
index 402724ce01..b7b5a3d363 100644
--- a/vendor/github.com/blevesearch/bleve/search/query/bool_field.go
+++ b/vendor/github.com/blevesearch/bleve/search/query/bool_field.go
@@ -22,7 +22,7 @@ import (
)
type BoolFieldQuery struct {
- Bool bool `json:"bool"`
+ Bool bool `json:"bool"`
FieldVal string `json:"field,omitempty"`
BoostVal *Boost `json:"boost,omitempty"`
}
@@ -39,20 +39,19 @@ func (q *BoolFieldQuery) SetBoost(b float64) {
q.BoostVal = &boost
}
-func (q *BoolFieldQuery) Boost() float64{
- return q.BoostVal.Value()
+func (q *BoolFieldQuery) Boost() float64 {
+ return q.BoostVal.Value()
}
func (q *BoolFieldQuery) SetField(f string) {
q.FieldVal = f
}
-func (q *BoolFieldQuery) Field() string{
+func (q *BoolFieldQuery) Field() string {
return q.FieldVal
}
-
-func (q *BoolFieldQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
+func (q *BoolFieldQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, options search.SearcherOptions) (search.Searcher, error) {
field := q.FieldVal
if q.FieldVal == "" {
field = m.DefaultSearchField()
@@ -61,5 +60,5 @@ func (q *BoolFieldQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, e
if q.Bool {
term = "T"
}
- return searcher.NewTermSearcher(i, term, field, q.BoostVal.Value(), explain)
+ return searcher.NewTermSearcher(i, term, field, q.BoostVal.Value(), options)
}
diff --git a/vendor/github.com/blevesearch/bleve/search/query/boolean.go b/vendor/github.com/blevesearch/bleve/search/query/boolean.go
index 2fe75ff994..3cfa1d99f3 100644
--- a/vendor/github.com/blevesearch/bleve/search/query/boolean.go
+++ b/vendor/github.com/blevesearch/bleve/search/query/boolean.go
@@ -25,10 +25,11 @@ import (
)
type BooleanQuery struct {
- Must Query `json:"must,omitempty"`
- Should Query `json:"should,omitempty"`
- MustNot Query `json:"must_not,omitempty"`
- BoostVal *Boost `json:"boost,omitempty"`
+ Must Query `json:"must,omitempty"`
+ Should Query `json:"should,omitempty"`
+ MustNot Query `json:"must_not,omitempty"`
+ BoostVal *Boost `json:"boost,omitempty"`
+ queryStringMode bool
}
// NewBooleanQuery creates a compound Query composed
@@ -55,6 +56,15 @@ func NewBooleanQuery(must []Query, should []Query, mustNot []Query) *BooleanQuer
return &rv
}
+func NewBooleanQueryForQueryString(must []Query, should []Query, mustNot []Query) *BooleanQuery {
+ rv := NewBooleanQuery(nil, nil, nil)
+ rv.queryStringMode = true
+ rv.AddMust(must...)
+ rv.AddShould(should...)
+ rv.AddMustNot(mustNot...)
+ return rv
+}
+
// SetMinShould requires that at least minShould of the
// should Queries must be satisfied.
func (q *BooleanQuery) SetMinShould(minShould float64) {
@@ -63,7 +73,9 @@ func (q *BooleanQuery) SetMinShould(minShould float64) {
func (q *BooleanQuery) AddMust(m ...Query) {
if q.Must == nil {
- q.Must = NewConjunctionQuery([]Query{})
+ tmp := NewConjunctionQuery([]Query{})
+ tmp.queryStringMode = q.queryStringMode
+ q.Must = tmp
}
for _, mq := range m {
q.Must.(*ConjunctionQuery).AddQuery(mq)
@@ -72,7 +84,9 @@ func (q *BooleanQuery) AddMust(m ...Query) {
func (q *BooleanQuery) AddShould(m ...Query) {
if q.Should == nil {
- q.Should = NewDisjunctionQuery([]Query{})
+ tmp := NewDisjunctionQuery([]Query{})
+ tmp.queryStringMode = q.queryStringMode
+ q.Should = tmp
}
for _, mq := range m {
q.Should.(*DisjunctionQuery).AddQuery(mq)
@@ -81,7 +95,9 @@ func (q *BooleanQuery) AddShould(m ...Query) {
func (q *BooleanQuery) AddMustNot(m ...Query) {
if q.MustNot == nil {
- q.MustNot = NewDisjunctionQuery([]Query{})
+ tmp := NewDisjunctionQuery([]Query{})
+ tmp.queryStringMode = q.queryStringMode
+ q.MustNot = tmp
}
for _, mq := range m {
q.MustNot.(*DisjunctionQuery).AddQuery(mq)
@@ -93,44 +109,67 @@ func (q *BooleanQuery) SetBoost(b float64) {
q.BoostVal = &boost
}
-func (q *BooleanQuery) Boost() float64{
+func (q *BooleanQuery) Boost() float64 {
return q.BoostVal.Value()
}
-func (q *BooleanQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
+func (q *BooleanQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, options search.SearcherOptions) (search.Searcher, error) {
var err error
var mustNotSearcher search.Searcher
if q.MustNot != nil {
- mustNotSearcher, err = q.MustNot.Searcher(i, m, explain)
+ mustNotSearcher, err = q.MustNot.Searcher(i, m, options)
if err != nil {
return nil, err
}
- if q.Must == nil && q.Should == nil {
- q.Must = NewMatchAllQuery()
+ // if must not is MatchNone, reset it to nil
+ if _, ok := mustNotSearcher.(*searcher.MatchNoneSearcher); ok {
+ mustNotSearcher = nil
}
}
var mustSearcher search.Searcher
if q.Must != nil {
- mustSearcher, err = q.Must.Searcher(i, m, explain)
+ mustSearcher, err = q.Must.Searcher(i, m, options)
if err != nil {
return nil, err
}
+ // if must searcher is MatchNone, reset it to nil
+ if _, ok := mustSearcher.(*searcher.MatchNoneSearcher); ok {
+ mustSearcher = nil
+ }
}
var shouldSearcher search.Searcher
if q.Should != nil {
- shouldSearcher, err = q.Should.Searcher(i, m, explain)
+ shouldSearcher, err = q.Should.Searcher(i, m, options)
+ if err != nil {
+ return nil, err
+ }
+ // if should searcher is MatchNone, reset it to nil
+ if _, ok := shouldSearcher.(*searcher.MatchNoneSearcher); ok {
+ shouldSearcher = nil
+ }
+ }
+
+ // if all 3 are nil, return MatchNone
+ if mustSearcher == nil && shouldSearcher == nil && mustNotSearcher == nil {
+ return searcher.NewMatchNoneSearcher(i)
+ }
+
+ // if only mustNotSearcher, start with MatchAll
+ if mustSearcher == nil && shouldSearcher == nil && mustNotSearcher != nil {
+ mustSearcher, err = searcher.NewMatchAllSearcher(i, 1.0, options)
if err != nil {
return nil, err
}
}
+ // optimization, if only should searcher, just return it instead
if mustSearcher == nil && shouldSearcher != nil && mustNotSearcher == nil {
return shouldSearcher, nil
}
- return searcher.NewBooleanSearcher(i, mustSearcher, shouldSearcher, mustNotSearcher, explain)
+ return searcher.NewBooleanSearcher(i, mustSearcher, shouldSearcher, mustNotSearcher, options)
}
func (q *BooleanQuery) Validate() error {
diff --git a/vendor/github.com/blevesearch/bleve/search/query/conjunction.go b/vendor/github.com/blevesearch/bleve/search/query/conjunction.go
index e819d69760..39cc312de8 100644
--- a/vendor/github.com/blevesearch/bleve/search/query/conjunction.go
+++ b/vendor/github.com/blevesearch/bleve/search/query/conjunction.go
@@ -24,8 +24,9 @@ import (
)
type ConjunctionQuery struct {
- Conjuncts []Query `json:"conjuncts"`
- BoostVal *Boost `json:"boost,omitempty"`
+ Conjuncts []Query `json:"conjuncts"`
+ BoostVal *Boost `json:"boost,omitempty"`
+ queryStringMode bool
}
// NewConjunctionQuery creates a new compound Query.
@@ -41,7 +42,7 @@ func (q *ConjunctionQuery) SetBoost(b float64) {
q.BoostVal = &boost
}
-func (q *ConjunctionQuery) Boost() float64{
+func (q *ConjunctionQuery) Boost() float64 {
return q.BoostVal.Value()
}
@@ -51,11 +52,10 @@ func (q *ConjunctionQuery) AddQuery(aq ...Query) {
}
}
-func (q *ConjunctionQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
- ss := make([]search.Searcher, len(q.Conjuncts))
- for in, conjunct := range q.Conjuncts {
- var err error
- ss[in], err = conjunct.Searcher(i, m, explain)
+func (q *ConjunctionQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, options search.SearcherOptions) (search.Searcher, error) {
+ ss := make([]search.Searcher, 0, len(q.Conjuncts))
+ for _, conjunct := range q.Conjuncts {
+ sr, err := conjunct.Searcher(i, m, options)
if err != nil {
for _, searcher := range ss {
if searcher != nil {
@@ -64,8 +64,16 @@ func (q *ConjunctionQuery) Searcher(i index.IndexReader, m mapping.IndexMapping,
}
return nil, err
}
+ if _, ok := sr.(*searcher.MatchNoneSearcher); ok && q.queryStringMode {
+ // in query string mode, skip match none
+ continue
+ }
+ ss = append(ss, sr)
+ }
+ if len(ss) < 1 {
+ return searcher.NewMatchNoneSearcher(i)
}
- return searcher.NewConjunctionSearcher(i, ss, explain)
+ return searcher.NewConjunctionSearcher(i, ss, options)
}
func (q *ConjunctionQuery) Validate() error {
diff --git a/vendor/github.com/blevesearch/bleve/search/query/date_range.go b/vendor/github.com/blevesearch/bleve/search/query/date_range.go
index 8c5811f151..ff67a7bb70 100644
--- a/vendor/github.com/blevesearch/bleve/search/query/date_range.go
+++ b/vendor/github.com/blevesearch/bleve/search/query/date_range.go
@@ -113,20 +113,19 @@ func (q *DateRangeQuery) SetBoost(b float64) {
q.BoostVal = &boost
}
-func (q *DateRangeQuery) Boost() float64{
+func (q *DateRangeQuery) Boost() float64 {
return q.BoostVal.Value()
}
-
func (q *DateRangeQuery) SetField(f string) {
q.FieldVal = f
}
-func (q *DateRangeQuery) Field() string{
+func (q *DateRangeQuery) Field() string {
return q.FieldVal
}
-func (q *DateRangeQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
+func (q *DateRangeQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, options search.SearcherOptions) (search.Searcher, error) {
min, max, err := q.parseEndpoints()
if err != nil {
return nil, err
@@ -137,7 +136,7 @@ func (q *DateRangeQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, e
field = m.DefaultSearchField()
}
- return searcher.NewNumericRangeSearcher(i, min, max, q.InclusiveStart, q.InclusiveEnd, field, q.BoostVal.Value(), explain)
+ return searcher.NewNumericRangeSearcher(i, min, max, q.InclusiveStart, q.InclusiveEnd, field, q.BoostVal.Value(), options)
}
func (q *DateRangeQuery) parseEndpoints() (*float64, *float64, error) {
diff --git a/vendor/github.com/blevesearch/bleve/search/query/disjunction.go b/vendor/github.com/blevesearch/bleve/search/query/disjunction.go
index 08f47c4110..dacc3a75b1 100644
--- a/vendor/github.com/blevesearch/bleve/search/query/disjunction.go
+++ b/vendor/github.com/blevesearch/bleve/search/query/disjunction.go
@@ -25,9 +25,10 @@ import (
)
type DisjunctionQuery struct {
- Disjuncts []Query `json:"disjuncts"`
- BoostVal *Boost `json:"boost,omitempty"`
- Min float64 `json:"min"`
+ Disjuncts []Query `json:"disjuncts"`
+ BoostVal *Boost `json:"boost,omitempty"`
+ Min float64 `json:"min"`
+ queryStringMode bool
}
// NewDisjunctionQuery creates a new compound Query.
@@ -43,11 +44,10 @@ func (q *DisjunctionQuery) SetBoost(b float64) {
q.BoostVal = &boost
}
-func (q *DisjunctionQuery) Boost() float64{
+func (q *DisjunctionQuery) Boost() float64 {
return q.BoostVal.Value()
}
-
func (q *DisjunctionQuery) AddQuery(aq ...Query) {
for _, aaq := range aq {
q.Disjuncts = append(q.Disjuncts, aaq)
@@ -58,11 +58,10 @@ func (q *DisjunctionQuery) SetMin(m float64) {
q.Min = m
}
-func (q *DisjunctionQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
- ss := make([]search.Searcher, len(q.Disjuncts))
- for in, disjunct := range q.Disjuncts {
- var err error
- ss[in], err = disjunct.Searcher(i, m, explain)
+func (q *DisjunctionQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, options search.SearcherOptions) (search.Searcher, error) {
+ ss := make([]search.Searcher, 0, len(q.Disjuncts))
+ for _, disjunct := range q.Disjuncts {
+ sr, err := disjunct.Searcher(i, m, options)
if err != nil {
for _, searcher := range ss {
if searcher != nil {
@@ -71,8 +70,16 @@ func (q *DisjunctionQuery) Searcher(i index.IndexReader, m mapping.IndexMapping,
}
return nil, err
}
+ if _, ok := sr.(*searcher.MatchNoneSearcher); ok && q.queryStringMode {
+ // in query string mode, skip match none
+ continue
+ }
+ ss = append(ss, sr)
+ }
+ if len(ss) < 1 {
+ return searcher.NewMatchNoneSearcher(i)
}
- return searcher.NewDisjunctionSearcher(i, ss, q.Min, explain)
+ return searcher.NewDisjunctionSearcher(i, ss, q.Min, options)
}
func (q *DisjunctionQuery) Validate() error {
diff --git a/vendor/github.com/blevesearch/bleve/search/query/docid.go b/vendor/github.com/blevesearch/bleve/search/query/docid.go
index c633d947ee..3b865f93ac 100644
--- a/vendor/github.com/blevesearch/bleve/search/query/docid.go
+++ b/vendor/github.com/blevesearch/bleve/search/query/docid.go
@@ -40,10 +40,10 @@ func (q *DocIDQuery) SetBoost(b float64) {
q.BoostVal = &boost
}
-func (q *DocIDQuery) Boost() float64{
+func (q *DocIDQuery) Boost() float64 {
return q.BoostVal.Value()
}
-func (q *DocIDQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
- return searcher.NewDocIDSearcher(i, q.IDs, q.BoostVal.Value(), explain)
+func (q *DocIDQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, options search.SearcherOptions) (search.Searcher, error) {
+ return searcher.NewDocIDSearcher(i, q.IDs, q.BoostVal.Value(), options)
}
diff --git a/vendor/github.com/blevesearch/bleve/search/query/fuzzy.go b/vendor/github.com/blevesearch/bleve/search/query/fuzzy.go
index 6effd3438f..f18982d407 100644
--- a/vendor/github.com/blevesearch/bleve/search/query/fuzzy.go
+++ b/vendor/github.com/blevesearch/bleve/search/query/fuzzy.go
@@ -48,7 +48,7 @@ func (q *FuzzyQuery) SetBoost(b float64) {
q.BoostVal = &boost
}
-func (q *FuzzyQuery) Boost() float64{
+func (q *FuzzyQuery) Boost() float64 {
return q.BoostVal.Value()
}
@@ -56,7 +56,7 @@ func (q *FuzzyQuery) SetField(f string) {
q.FieldVal = f
}
-func (q *FuzzyQuery) Field() string{
+func (q *FuzzyQuery) Field() string {
return q.FieldVal
}
@@ -68,10 +68,10 @@ func (q *FuzzyQuery) SetPrefix(p int) {
q.Prefix = p
}
-func (q *FuzzyQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
+func (q *FuzzyQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, options search.SearcherOptions) (search.Searcher, error) {
field := q.FieldVal
if q.FieldVal == "" {
field = m.DefaultSearchField()
}
- return searcher.NewFuzzySearcher(i, q.Term, q.Prefix, q.Fuzziness, field, q.BoostVal.Value(), explain)
+ return searcher.NewFuzzySearcher(i, q.Term, q.Prefix, q.Fuzziness, field, q.BoostVal.Value(), options)
}
diff --git a/vendor/github.com/blevesearch/bleve/search/query/geo_boundingbox.go b/vendor/github.com/blevesearch/bleve/search/query/geo_boundingbox.go
new file mode 100644
index 0000000000..de6be4a583
--- /dev/null
+++ b/vendor/github.com/blevesearch/bleve/search/query/geo_boundingbox.go
@@ -0,0 +1,113 @@
+// Copyright (c) 2017 Couchbase, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package query
+
+import (
+ "encoding/json"
+ "fmt"
+
+ "github.com/blevesearch/bleve/geo"
+ "github.com/blevesearch/bleve/index"
+ "github.com/blevesearch/bleve/mapping"
+ "github.com/blevesearch/bleve/search"
+ "github.com/blevesearch/bleve/search/searcher"
+)
+
+type GeoBoundingBoxQuery struct {
+ TopLeft []float64 `json:"top_left,omitempty"`
+ BottomRight []float64 `json:"bottom_right,omitempty"`
+ FieldVal string `json:"field,omitempty"`
+ BoostVal *Boost `json:"boost,omitempty"`
+}
+
+func NewGeoBoundingBoxQuery(topLeftLon, topLeftLat, bottomRightLon, bottomRightLat float64) *GeoBoundingBoxQuery {
+ return &GeoBoundingBoxQuery{
+ TopLeft: []float64{topLeftLon, topLeftLat},
+ BottomRight: []float64{bottomRightLon, bottomRightLat},
+ }
+}
+
+func (q *GeoBoundingBoxQuery) SetBoost(b float64) {
+ boost := Boost(b)
+ q.BoostVal = &boost
+}
+
+func (q *GeoBoundingBoxQuery) Boost() float64 {
+ return q.BoostVal.Value()
+}
+
+func (q *GeoBoundingBoxQuery) SetField(f string) {
+ q.FieldVal = f
+}
+
+func (q *GeoBoundingBoxQuery) Field() string {
+ return q.FieldVal
+}
+
+func (q *GeoBoundingBoxQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, options search.SearcherOptions) (search.Searcher, error) {
+ field := q.FieldVal
+ if q.FieldVal == "" {
+ field = m.DefaultSearchField()
+ }
+
+ if q.BottomRight[0] < q.TopLeft[0] {
+ // cross date line, rewrite as two parts
+
+ leftSearcher, err := searcher.NewGeoBoundingBoxSearcher(i, -180, q.BottomRight[1], q.BottomRight[0], q.TopLeft[1], field, q.BoostVal.Value(), options, true)
+ if err != nil {
+ return nil, err
+ }
+ rightSearcher, err := searcher.NewGeoBoundingBoxSearcher(i, q.TopLeft[0], q.BottomRight[1], 180, q.TopLeft[1], field, q.BoostVal.Value(), options, true)
+ if err != nil {
+ _ = leftSearcher.Close()
+ return nil, err
+ }
+
+ return searcher.NewDisjunctionSearcher(i, []search.Searcher{leftSearcher, rightSearcher}, 0, options)
+ }
+
+ return searcher.NewGeoBoundingBoxSearcher(i, q.TopLeft[0], q.BottomRight[1], q.BottomRight[0], q.TopLeft[1], field, q.BoostVal.Value(), options, true)
+}
+
+func (q *GeoBoundingBoxQuery) Validate() error {
+ return nil
+}
+
+func (q *GeoBoundingBoxQuery) UnmarshalJSON(data []byte) error {
+ tmp := struct {
+ TopLeft interface{} `json:"top_left,omitempty"`
+ BottomRight interface{} `json:"bottom_right,omitempty"`
+ FieldVal string `json:"field,omitempty"`
+ BoostVal *Boost `json:"boost,omitempty"`
+ }{}
+ err := json.Unmarshal(data, &tmp)
+ if err != nil {
+ return err
+ }
+ // now use our generic point parsing code from the geo package
+ lon, lat, found := geo.ExtractGeoPoint(tmp.TopLeft)
+ if !found {
+ return fmt.Errorf("geo location top_left not in a valid format")
+ }
+ q.TopLeft = []float64{lon, lat}
+ lon, lat, found = geo.ExtractGeoPoint(tmp.BottomRight)
+ if !found {
+ return fmt.Errorf("geo location bottom_right not in a valid format")
+ }
+ q.BottomRight = []float64{lon, lat}
+ q.FieldVal = tmp.FieldVal
+ q.BoostVal = tmp.BoostVal
+ return nil
+}
diff --git a/vendor/github.com/blevesearch/bleve/search/query/geo_distance.go b/vendor/github.com/blevesearch/bleve/search/query/geo_distance.go
new file mode 100644
index 0000000000..ef3aa88c99
--- /dev/null
+++ b/vendor/github.com/blevesearch/bleve/search/query/geo_distance.go
@@ -0,0 +1,100 @@
+// Copyright (c) 2017 Couchbase, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package query
+
+import (
+ "encoding/json"
+ "fmt"
+
+ "github.com/blevesearch/bleve/geo"
+ "github.com/blevesearch/bleve/index"
+ "github.com/blevesearch/bleve/mapping"
+ "github.com/blevesearch/bleve/search"
+ "github.com/blevesearch/bleve/search/searcher"
+)
+
+type GeoDistanceQuery struct {
+ Location []float64 `json:"location,omitempty"`
+ Distance string `json:"distance,omitempty"`
+ FieldVal string `json:"field,omitempty"`
+ BoostVal *Boost `json:"boost,omitempty"`
+}
+
+func NewGeoDistanceQuery(lon, lat float64, distance string) *GeoDistanceQuery {
+ return &GeoDistanceQuery{
+ Location: []float64{lon, lat},
+ Distance: distance,
+ }
+}
+
+func (q *GeoDistanceQuery) SetBoost(b float64) {
+ boost := Boost(b)
+ q.BoostVal = &boost
+}
+
+func (q *GeoDistanceQuery) Boost() float64 {
+ return q.BoostVal.Value()
+}
+
+func (q *GeoDistanceQuery) SetField(f string) {
+ q.FieldVal = f
+}
+
+func (q *GeoDistanceQuery) Field() string {
+ return q.FieldVal
+}
+
+func (q *GeoDistanceQuery) Searcher(i index.IndexReader, m mapping.IndexMapping,
+ options search.SearcherOptions) (search.Searcher, error) {
+ field := q.FieldVal
+ if q.FieldVal == "" {
+ field = m.DefaultSearchField()
+ }
+
+ dist, err := geo.ParseDistance(q.Distance)
+ if err != nil {
+ return nil, err
+ }
+
+ return searcher.NewGeoPointDistanceSearcher(i, q.Location[0], q.Location[1],
+ dist, field, q.BoostVal.Value(), options)
+}
+
+func (q *GeoDistanceQuery) Validate() error {
+ return nil
+}
+
+func (q *GeoDistanceQuery) UnmarshalJSON(data []byte) error {
+ tmp := struct {
+ Location interface{} `json:"location,omitempty"`
+ Distance string `json:"distance,omitempty"`
+ FieldVal string `json:"field,omitempty"`
+ BoostVal *Boost `json:"boost,omitempty"`
+ }{}
+ err := json.Unmarshal(data, &tmp)
+ if err != nil {
+ return err
+ }
+ // now use our generic point parsing code from the geo package
+ lon, lat, found := geo.ExtractGeoPoint(tmp.Location)
+ if !found {
+ return fmt.Errorf("geo location not in a valid format")
+ }
+ q.Location = []float64{lon, lat}
+ q.Distance = tmp.Distance
+ q.FieldVal = tmp.FieldVal
+ q.BoostVal = tmp.BoostVal
+ return nil
+}
diff --git a/vendor/github.com/blevesearch/bleve/search/query/match.go b/vendor/github.com/blevesearch/bleve/search/query/match.go
index 6d0b005333..36c9ee4a47 100644
--- a/vendor/github.com/blevesearch/bleve/search/query/match.go
+++ b/vendor/github.com/blevesearch/bleve/search/query/match.go
@@ -90,7 +90,7 @@ func (q *MatchQuery) SetBoost(b float64) {
q.BoostVal = &boost
}
-func (q *MatchQuery) Boost() float64{
+func (q *MatchQuery) Boost() float64 {
return q.BoostVal.Value()
}
@@ -98,7 +98,7 @@ func (q *MatchQuery) SetField(f string) {
q.FieldVal = f
}
-func (q *MatchQuery) Field() string{
+func (q *MatchQuery) Field() string {
return q.FieldVal
}
@@ -114,7 +114,7 @@ func (q *MatchQuery) SetOperator(operator MatchQueryOperator) {
q.Operator = operator
}
-func (q *MatchQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
+func (q *MatchQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, options search.SearcherOptions) (search.Searcher, error) {
field := q.FieldVal
if q.FieldVal == "" {
@@ -160,17 +160,17 @@ func (q *MatchQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, expla
shouldQuery := NewDisjunctionQuery(tqs)
shouldQuery.SetMin(1)
shouldQuery.SetBoost(q.BoostVal.Value())
- return shouldQuery.Searcher(i, m, explain)
+ return shouldQuery.Searcher(i, m, options)
case MatchQueryOperatorAnd:
mustQuery := NewConjunctionQuery(tqs)
mustQuery.SetBoost(q.BoostVal.Value())
- return mustQuery.Searcher(i, m, explain)
+ return mustQuery.Searcher(i, m, options)
default:
return nil, fmt.Errorf("unhandled operator %d", q.Operator)
}
}
noneQuery := NewMatchNoneQuery()
- return noneQuery.Searcher(i, m, explain)
+ return noneQuery.Searcher(i, m, options)
}
diff --git a/vendor/github.com/blevesearch/bleve/search/query/match_all.go b/vendor/github.com/blevesearch/bleve/search/query/match_all.go
index 9eb7eb95f7..7fbe1f99db 100644
--- a/vendor/github.com/blevesearch/bleve/search/query/match_all.go
+++ b/vendor/github.com/blevesearch/bleve/search/query/match_all.go
@@ -38,14 +38,12 @@ func (q *MatchAllQuery) SetBoost(b float64) {
q.BoostVal = &boost
}
-func (q *MatchAllQuery) Boost() float64{
+func (q *MatchAllQuery) Boost() float64 {
return q.BoostVal.Value()
}
-
-
-func (q *MatchAllQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
- return searcher.NewMatchAllSearcher(i, q.BoostVal.Value(), explain)
+func (q *MatchAllQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, options search.SearcherOptions) (search.Searcher, error) {
+ return searcher.NewMatchAllSearcher(i, q.BoostVal.Value(), options)
}
func (q *MatchAllQuery) MarshalJSON() ([]byte, error) {
diff --git a/vendor/github.com/blevesearch/bleve/search/query/match_none.go b/vendor/github.com/blevesearch/bleve/search/query/match_none.go
index 5264c5a6bd..dc2ea780c1 100644
--- a/vendor/github.com/blevesearch/bleve/search/query/match_none.go
+++ b/vendor/github.com/blevesearch/bleve/search/query/match_none.go
@@ -38,11 +38,11 @@ func (q *MatchNoneQuery) SetBoost(b float64) {
q.BoostVal = &boost
}
-func (q *MatchNoneQuery) Boost() float64{
+func (q *MatchNoneQuery) Boost() float64 {
return q.BoostVal.Value()
}
-func (q *MatchNoneQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
+func (q *MatchNoneQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, options search.SearcherOptions) (search.Searcher, error) {
return searcher.NewMatchNoneSearcher(i)
}
diff --git a/vendor/github.com/blevesearch/bleve/search/query/match_phrase.go b/vendor/github.com/blevesearch/bleve/search/query/match_phrase.go
index a148808ff3..51be35526f 100644
--- a/vendor/github.com/blevesearch/bleve/search/query/match_phrase.go
+++ b/vendor/github.com/blevesearch/bleve/search/query/match_phrase.go
@@ -49,7 +49,7 @@ func (q *MatchPhraseQuery) SetBoost(b float64) {
q.BoostVal = &boost
}
-func (q *MatchPhraseQuery) Boost() float64{
+func (q *MatchPhraseQuery) Boost() float64 {
return q.BoostVal.Value()
}
@@ -57,11 +57,11 @@ func (q *MatchPhraseQuery) SetField(f string) {
q.FieldVal = f
}
-func (q *MatchPhraseQuery) Field() string{
+func (q *MatchPhraseQuery) Field() string {
return q.FieldVal
}
-func (q *MatchPhraseQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
+func (q *MatchPhraseQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, options search.SearcherOptions) (search.Searcher, error) {
field := q.FieldVal
if q.FieldVal == "" {
field = m.DefaultSearchField()
@@ -81,15 +81,15 @@ func (q *MatchPhraseQuery) Searcher(i index.IndexReader, m mapping.IndexMapping,
tokens := analyzer.Analyze([]byte(q.MatchPhrase))
if len(tokens) > 0 {
phrase := tokenStreamToPhrase(tokens)
- phraseQuery := NewPhraseQuery(phrase, field)
+ phraseQuery := NewMultiPhraseQuery(phrase, field)
phraseQuery.SetBoost(q.BoostVal.Value())
- return phraseQuery.Searcher(i, m, explain)
+ return phraseQuery.Searcher(i, m, options)
}
noneQuery := NewMatchNoneQuery()
- return noneQuery.Searcher(i, m, explain)
+ return noneQuery.Searcher(i, m, options)
}
-func tokenStreamToPhrase(tokens analysis.TokenStream) []string {
+func tokenStreamToPhrase(tokens analysis.TokenStream) [][]string {
firstPosition := int(^uint(0) >> 1)
lastPosition := 0
for _, token := range tokens {
@@ -102,13 +102,10 @@ func tokenStreamToPhrase(tokens analysis.TokenStream) []string {
}
phraseLen := lastPosition - firstPosition + 1
if phraseLen > 0 {
- rv := make([]string, phraseLen)
- for i := 0; i < phraseLen; i++ {
- rv[i] = ""
- }
+ rv := make([][]string, phraseLen)
for _, token := range tokens {
pos := token.Position - firstPosition
- rv[pos] = string(token.Term)
+ rv[pos] = append(rv[pos], string(token.Term))
}
return rv
}
diff --git a/vendor/github.com/blevesearch/bleve/search/query/multi_phrase.go b/vendor/github.com/blevesearch/bleve/search/query/multi_phrase.go
new file mode 100644
index 0000000000..8a7c9b6ade
--- /dev/null
+++ b/vendor/github.com/blevesearch/bleve/search/query/multi_phrase.go
@@ -0,0 +1,80 @@
+// Copyright (c) 2014 Couchbase, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package query
+
+import (
+ "encoding/json"
+ "fmt"
+
+ "github.com/blevesearch/bleve/index"
+ "github.com/blevesearch/bleve/mapping"
+ "github.com/blevesearch/bleve/search"
+ "github.com/blevesearch/bleve/search/searcher"
+)
+
+type MultiPhraseQuery struct {
+ Terms [][]string `json:"terms"`
+ Field string `json:"field,omitempty"`
+ BoostVal *Boost `json:"boost,omitempty"`
+}
+
+// NewMultiPhraseQuery creates a new Query for finding
+// term phrases in the index.
+// It is like PhraseQuery, but each position in the
+// phrase may be satisfied by a list of terms
+// as opposed to just one.
+// At least one of the terms must exist in the correct
+// order, at the correct index offsets, in the
+// specified field. Queried field must have been indexed with
+// IncludeTermVectors set to true.
+func NewMultiPhraseQuery(terms [][]string, field string) *MultiPhraseQuery {
+ return &MultiPhraseQuery{
+ Terms: terms,
+ Field: field,
+ }
+}
+
+func (q *MultiPhraseQuery) SetBoost(b float64) {
+ boost := Boost(b)
+ q.BoostVal = &boost
+}
+
+func (q *MultiPhraseQuery) Boost() float64 {
+ return q.BoostVal.Value()
+}
+
+func (q *MultiPhraseQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, options search.SearcherOptions) (search.Searcher, error) {
+ return searcher.NewMultiPhraseSearcher(i, q.Terms, q.Field, options)
+}
+
+func (q *MultiPhraseQuery) Validate() error {
+ if len(q.Terms) < 1 {
+ return fmt.Errorf("phrase query must contain at least one term")
+ }
+ return nil
+}
+
+func (q *MultiPhraseQuery) UnmarshalJSON(data []byte) error {
+ type _mphraseQuery MultiPhraseQuery
+ tmp := _mphraseQuery{}
+ err := json.Unmarshal(data, &tmp)
+ if err != nil {
+ return err
+ }
+ q.Terms = tmp.Terms
+ q.Field = tmp.Field
+ q.BoostVal = tmp.BoostVal
+ return nil
+}
diff --git a/vendor/github.com/blevesearch/bleve/search/query/numeric_range.go b/vendor/github.com/blevesearch/bleve/search/query/numeric_range.go
index 93f7fd6b27..ea3f068862 100644
--- a/vendor/github.com/blevesearch/bleve/search/query/numeric_range.go
+++ b/vendor/github.com/blevesearch/bleve/search/query/numeric_range.go
@@ -59,7 +59,7 @@ func (q *NumericRangeQuery) SetBoost(b float64) {
q.BoostVal = &boost
}
-func (q *NumericRangeQuery) Boost() float64{
+func (q *NumericRangeQuery) Boost() float64 {
return q.BoostVal.Value()
}
@@ -67,16 +67,16 @@ func (q *NumericRangeQuery) SetField(f string) {
q.FieldVal = f
}
-func (q *NumericRangeQuery) Field() string{
+func (q *NumericRangeQuery) Field() string {
return q.FieldVal
}
-func (q *NumericRangeQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
+func (q *NumericRangeQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, options search.SearcherOptions) (search.Searcher, error) {
field := q.FieldVal
if q.FieldVal == "" {
field = m.DefaultSearchField()
}
- return searcher.NewNumericRangeSearcher(i, q.Min, q.Max, q.InclusiveMin, q.InclusiveMax, field, q.BoostVal.Value(), explain)
+ return searcher.NewNumericRangeSearcher(i, q.Min, q.Max, q.InclusiveMin, q.InclusiveMax, field, q.BoostVal.Value(), options)
}
func (q *NumericRangeQuery) Validate() error {
diff --git a/vendor/github.com/blevesearch/bleve/search/query/phrase.go b/vendor/github.com/blevesearch/bleve/search/query/phrase.go
index 0cd608b8bd..dff1a02d4b 100644
--- a/vendor/github.com/blevesearch/bleve/search/query/phrase.go
+++ b/vendor/github.com/blevesearch/bleve/search/query/phrase.go
@@ -25,10 +25,9 @@ import (
)
type PhraseQuery struct {
- Terms []string `json:"terms"`
- Field string `json:"field,omitempty"`
- BoostVal *Boost `json:"boost,omitempty"`
- termQueries []Query
+ Terms []string `json:"terms"`
+ Field string `json:"field,omitempty"`
+ BoostVal *Boost `json:"boost,omitempty"`
}
// NewPhraseQuery creates a new Query for finding
@@ -38,18 +37,9 @@ type PhraseQuery struct {
// specified field. Queried field must have been indexed with
// IncludeTermVectors set to true.
func NewPhraseQuery(terms []string, field string) *PhraseQuery {
- termQueries := make([]Query, 0)
- for _, term := range terms {
- if term != "" {
- tq := NewTermQuery(term)
- tq.SetField(field)
- termQueries = append(termQueries, tq)
- }
- }
return &PhraseQuery{
- Terms: terms,
- Field: field,
- termQueries: termQueries,
+ Terms: terms,
+ Field: field,
}
}
@@ -58,22 +48,16 @@ func (q *PhraseQuery) SetBoost(b float64) {
q.BoostVal = &boost
}
-func (q *PhraseQuery) Boost() float64{
+func (q *PhraseQuery) Boost() float64 {
return q.BoostVal.Value()
}
-func (q *PhraseQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
-
- conjunctionQuery := NewConjunctionQuery(q.termQueries)
- conjunctionSearcher, err := conjunctionQuery.Searcher(i, m, explain)
- if err != nil {
- return nil, err
- }
- return searcher.NewPhraseSearcher(i, conjunctionSearcher.(*searcher.ConjunctionSearcher), q.Terms)
+func (q *PhraseQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, options search.SearcherOptions) (search.Searcher, error) {
+ return searcher.NewPhraseSearcher(i, q.Terms, q.Field, options)
}
func (q *PhraseQuery) Validate() error {
- if len(q.termQueries) < 1 {
+ if len(q.Terms) < 1 {
return fmt.Errorf("phrase query must contain at least one term")
}
return nil
@@ -89,9 +73,5 @@ func (q *PhraseQuery) UnmarshalJSON(data []byte) error {
q.Terms = tmp.Terms
q.Field = tmp.Field
q.BoostVal = tmp.BoostVal
- q.termQueries = make([]Query, len(q.Terms))
- for i, term := range q.Terms {
- q.termQueries[i] = &TermQuery{Term: term, FieldVal: q.Field, BoostVal: q.BoostVal}
- }
return nil
}
diff --git a/vendor/github.com/blevesearch/bleve/search/query/prefix.go b/vendor/github.com/blevesearch/bleve/search/query/prefix.go
index d8c2bb2f92..4f5be2b26e 100644
--- a/vendor/github.com/blevesearch/bleve/search/query/prefix.go
+++ b/vendor/github.com/blevesearch/bleve/search/query/prefix.go
@@ -41,7 +41,7 @@ func (q *PrefixQuery) SetBoost(b float64) {
q.BoostVal = &boost
}
-func (q *PrefixQuery) Boost() float64{
+func (q *PrefixQuery) Boost() float64 {
return q.BoostVal.Value()
}
@@ -49,14 +49,14 @@ func (q *PrefixQuery) SetField(f string) {
q.FieldVal = f
}
-func (q *PrefixQuery) Field() string{
+func (q *PrefixQuery) Field() string {
return q.FieldVal
}
-func (q *PrefixQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
+func (q *PrefixQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, options search.SearcherOptions) (search.Searcher, error) {
field := q.FieldVal
if q.FieldVal == "" {
field = m.DefaultSearchField()
}
- return searcher.NewTermPrefixSearcher(i, q.Prefix, field, q.BoostVal.Value(), explain)
+ return searcher.NewTermPrefixSearcher(i, q.Prefix, field, q.BoostVal.Value(), options)
}
diff --git a/vendor/github.com/blevesearch/bleve/search/query/query.go b/vendor/github.com/blevesearch/bleve/search/query/query.go
index bb65a07526..1b0d94c012 100644
--- a/vendor/github.com/blevesearch/bleve/search/query/query.go
+++ b/vendor/github.com/blevesearch/bleve/search/query/query.go
@@ -36,7 +36,8 @@ func SetLog(l *log.Logger) {
// A Query represents a description of the type
// and parameters for a query into the index.
type Query interface {
- Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error)
+ Searcher(i index.IndexReader, m mapping.IndexMapping,
+ options search.SearcherOptions) (search.Searcher, error)
}
// A BoostableQuery represents a Query which can be boosted
@@ -122,7 +123,13 @@ func ParseQuery(input []byte) (Query, error) {
var rv PhraseQuery
err := json.Unmarshal(input, &rv)
if err != nil {
- return nil, err
+ // now try multi-phrase
+ var rv2 MultiPhraseQuery
+ err = json.Unmarshal(input, &rv2)
+ if err != nil {
+ return nil, err
+ }
+ return &rv2, nil
}
return &rv, nil
}
@@ -154,8 +161,8 @@ func ParseQuery(input []byte) (Query, error) {
}
return &rv, nil
}
- _, hasMin := tmp["min"]
- _, hasMax := tmp["max"]
+ _, hasMin := tmp["min"].(float64)
+ _, hasMax := tmp["max"].(float64)
if hasMin || hasMax {
var rv NumericRangeQuery
err := json.Unmarshal(input, &rv)
@@ -164,6 +171,16 @@ func ParseQuery(input []byte) (Query, error) {
}
return &rv, nil
}
+ _, hasMinStr := tmp["min"].(string)
+ _, hasMaxStr := tmp["max"].(string)
+ if hasMinStr || hasMaxStr {
+ var rv TermRangeQuery
+ err := json.Unmarshal(input, &rv)
+ if err != nil {
+ return nil, err
+ }
+ return &rv, nil
+ }
_, hasStart := tmp["start"]
_, hasEnd := tmp["end"]
if hasStart || hasEnd {
@@ -237,6 +254,25 @@ func ParseQuery(input []byte) (Query, error) {
}
return &rv, nil
}
+ _, hasTopLeft := tmp["top_left"]
+ _, hasBottomRight := tmp["bottom_right"]
+ if hasTopLeft && hasBottomRight {
+ var rv GeoBoundingBoxQuery
+ err := json.Unmarshal(input, &rv)
+ if err != nil {
+ return nil, err
+ }
+ return &rv, nil
+ }
+ _, hasDistance := tmp["distance"]
+ if hasDistance {
+ var rv GeoDistanceQuery
+ err := json.Unmarshal(input, &rv)
+ if err != nil {
+ return nil, err
+ }
+ return &rv, nil
+ }
return nil, fmt.Errorf("unknown query type")
}
@@ -300,14 +336,6 @@ func expandQuery(m mapping.IndexMapping, query Query) (Query, error) {
return nil, err
}
return &q, nil
- case *PhraseQuery:
- q := *query.(*PhraseQuery)
- children, err := expandSlice(q.termQueries)
- if err != nil {
- return nil, err
- }
- q.termQueries = children
- return &q, nil
default:
return query, nil
}
diff --git a/vendor/github.com/blevesearch/bleve/search/query/query_string.go b/vendor/github.com/blevesearch/bleve/search/query/query_string.go
index d8f421f451..ecafe6bc05 100644
--- a/vendor/github.com/blevesearch/bleve/search/query/query_string.go
+++ b/vendor/github.com/blevesearch/bleve/search/query/query_string.go
@@ -39,16 +39,20 @@ func (q *QueryStringQuery) SetBoost(b float64) {
q.BoostVal = &boost
}
-func (q *QueryStringQuery) Boost() float64{
+func (q *QueryStringQuery) Boost() float64 {
return q.BoostVal.Value()
}
-func (q *QueryStringQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
+func (q *QueryStringQuery) Parse() (Query, error) {
+ return parseQuerySyntax(q.Query)
+}
+
+func (q *QueryStringQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, options search.SearcherOptions) (search.Searcher, error) {
newQuery, err := parseQuerySyntax(q.Query)
if err != nil {
return nil, err
}
- return newQuery.Searcher(i, m, explain)
+ return newQuery.Searcher(i, m, options)
}
func (q *QueryStringQuery) Validate() error {
diff --git a/vendor/github.com/blevesearch/bleve/search/query/query_string.y b/vendor/github.com/blevesearch/bleve/search/query/query_string.y
index d703be28c1..d3e5ac9d7e 100644
--- a/vendor/github.com/blevesearch/bleve/search/query/query_string.y
+++ b/vendor/github.com/blevesearch/bleve/search/query/query_string.y
@@ -27,6 +27,7 @@ tEQUAL tTILDE
%type <s> tSTRING
%type <s> tPHRASE
%type <s> tNUMBER
+%type <s> posOrNegNumber
%type <s> tTILDE
%type <s> tBOOST
%type <q> searchBase
@@ -127,7 +128,15 @@ tSTRING tCOLON tSTRING tTILDE {
tNUMBER {
str := $1
logDebugGrammar("STRING - %s", str)
- q := NewMatchQuery(str)
+ q1 := NewMatchQuery(str)
+ val, err := strconv.ParseFloat($1, 64)
+ if err != nil {
+ yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("error parsing number: %v", err))
+ }
+ inclusive := true
+ q2 := NewNumericRangeInclusiveQuery(&val, &val, &inclusive, &inclusive)
+ q := NewDisjunctionQuery([]Query{q1,q2})
+ q.queryStringMode = true
$$ = q
}
|
@@ -154,12 +163,21 @@ tSTRING tCOLON tSTRING {
$$ = q
}
|
-tSTRING tCOLON tNUMBER {
+tSTRING tCOLON posOrNegNumber {
field := $1
str := $3
logDebugGrammar("FIELD - %s STRING - %s", field, str)
- q := NewMatchQuery(str)
- q.SetField(field)
+ q1 := NewMatchQuery(str)
+ q1.SetField(field)
+ val, err := strconv.ParseFloat($3, 64)
+ if err != nil {
+ yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("error parsing number: %v", err))
+ }
+ inclusive := true
+ q2 := NewNumericRangeInclusiveQuery(&val, &val, &inclusive, &inclusive)
+ q2.SetField(field)
+ q := NewDisjunctionQuery([]Query{q1,q2})
+ q.queryStringMode = true
$$ = q
}
|
@@ -172,9 +190,12 @@ tSTRING tCOLON tPHRASE {
$$ = q
}
|
-tSTRING tCOLON tGREATER tNUMBER {
+tSTRING tCOLON tGREATER posOrNegNumber {
field := $1
- min, _ := strconv.ParseFloat($4, 64)
+ min, err := strconv.ParseFloat($4, 64)
+ if err != nil {
+ yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("error parsing number: %v", err))
+ }
minInclusive := false
logDebugGrammar("FIELD - GREATER THAN %f", min)
q := NewNumericRangeInclusiveQuery(&min, nil, &minInclusive, nil)
@@ -182,9 +203,12 @@ tSTRING tCOLON tGREATER tNUMBER {
$$ = q
}
|
-tSTRING tCOLON tGREATER tEQUAL tNUMBER {
+tSTRING tCOLON tGREATER tEQUAL posOrNegNumber {
field := $1
- min, _ := strconv.ParseFloat($5, 64)
+ min, err := strconv.ParseFloat($5, 64)
+ if err != nil {
+ yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("error parsing number: %v", err))
+ }
minInclusive := true
logDebugGrammar("FIELD - GREATER THAN OR EQUAL %f", min)
q := NewNumericRangeInclusiveQuery(&min, nil, &minInclusive, nil)
@@ -192,9 +216,12 @@ tSTRING tCOLON tGREATER tEQUAL tNUMBER {
$$ = q
}
|
-tSTRING tCOLON tLESS tNUMBER {
+tSTRING tCOLON tLESS posOrNegNumber {
field := $1
- max, _ := strconv.ParseFloat($4, 64)
+ max, err := strconv.ParseFloat($4, 64)
+ if err != nil {
+ yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("error parsing number: %v", err))
+ }
maxInclusive := false
logDebugGrammar("FIELD - LESS THAN %f", max)
q := NewNumericRangeInclusiveQuery(nil, &max, nil, &maxInclusive)
@@ -202,9 +229,12 @@ tSTRING tCOLON tLESS tNUMBER {
$$ = q
}
|
-tSTRING tCOLON tLESS tEQUAL tNUMBER {
+tSTRING tCOLON tLESS tEQUAL posOrNegNumber {
field := $1
- max, _ := strconv.ParseFloat($5, 64)
+ max, err := strconv.ParseFloat($5, 64)
+ if err != nil {
+ yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("error parsing number: %v", err))
+ }
maxInclusive := true
logDebugGrammar("FIELD - LESS THAN OR EQUAL %f", max)
q := NewNumericRangeInclusiveQuery(nil, &max, nil, &maxInclusive)
@@ -287,3 +317,12 @@ tBOOST {
}
logDebugGrammar("BOOST %f", boost)
};
+
+posOrNegNumber:
+tNUMBER {
+ $$ = $1
+}
+|
+tMINUS tNUMBER {
+ $$ = "-" + $2
+};
diff --git a/vendor/github.com/blevesearch/bleve/search/query/query_string.y.go b/vendor/github.com/blevesearch/bleve/search/query/query_string.y.go
index 74ea00fc72..ac2d322263 100644
--- a/vendor/github.com/blevesearch/bleve/search/query/query_string.y.go
+++ b/vendor/github.com/blevesearch/bleve/search/query/query_string.y.go
@@ -70,57 +70,58 @@ var yyExca = [...]int{
-2, 5,
}
-const yyNprod = 26
+const yyNprod = 28
const yyPrivate = 57344
var yyTokenNames []string
var yyStates []string
-const yyLast = 31
+const yyLast = 42
var yyAct = [...]int{
- 16, 18, 21, 13, 27, 24, 17, 19, 20, 25,
- 22, 15, 26, 23, 9, 11, 31, 14, 29, 3,
- 10, 30, 2, 28, 5, 6, 7, 1, 4, 12,
- 8,
+ 17, 16, 18, 23, 22, 30, 3, 21, 19, 20,
+ 29, 26, 22, 22, 1, 21, 21, 15, 28, 25,
+ 24, 27, 34, 14, 22, 13, 31, 21, 32, 33,
+ 22, 9, 11, 21, 5, 6, 2, 10, 4, 12,
+ 7, 8,
}
var yyPact = [...]int{
- 18, -1000, -1000, 18, 10, -1000, -1000, -1000, -6, 3,
- -1000, -1000, -1000, -1000, -1000, -4, -12, -1000, -1000, 0,
- -1, -1000, -1000, 13, -1000, -1000, 11, -1000, -1000, -1000,
- -1000, -1000,
+ 28, -1000, -1000, 28, 27, -1000, -1000, -1000, 16, 9,
+ -1000, -1000, -1000, -1000, -1000, -3, -11, -1000, -1000, 6,
+ 5, -1000, -5, -1000, -1000, 23, -1000, -1000, 17, -1000,
+ -1000, -1000, -1000, -1000, -1000,
}
var yyPgo = [...]int{
- 0, 30, 29, 28, 27, 22, 19,
+ 0, 0, 41, 39, 38, 14, 36, 6,
}
var yyR1 = [...]int{
- 0, 4, 5, 5, 6, 3, 3, 3, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 2, 2,
+ 0, 5, 6, 6, 7, 4, 4, 4, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 3, 3, 1, 1,
}
var yyR2 = [...]int{
0, 1, 2, 1, 3, 0, 1, 1, 1, 2,
4, 1, 1, 3, 3, 3, 4, 5, 4, 5,
- 4, 5, 4, 5, 0, 1,
+ 4, 5, 4, 5, 0, 1, 1, 2,
}
var yyChk = [...]int{
- -1000, -4, -5, -6, -3, 6, 7, -5, -1, 4,
- 10, 5, -2, 9, 14, 8, 4, 10, 5, 11,
- 12, 14, 10, 13, 5, 10, 13, 5, 10, 5,
- 10, 5,
+ -1000, -5, -6, -7, -4, 6, 7, -6, -2, 4,
+ 10, 5, -3, 9, 14, 8, 4, -1, 5, 11,
+ 12, 10, 7, 14, -1, 13, 5, -1, 13, 5,
+ 10, -1, 5, -1, 5,
}
var yyDef = [...]int{
5, -2, 1, -2, 0, 6, 7, 2, 24, 8,
11, 12, 4, 25, 9, 0, 13, 14, 15, 0,
- 0, 10, 16, 0, 20, 18, 0, 22, 17, 21,
- 19, 23,
+ 0, 26, 0, 10, 16, 0, 20, 18, 0, 22,
+ 27, 17, 21, 19, 23,
}
var yyTok1 = [...]int{
@@ -474,25 +475,25 @@ yydefault:
case 1:
yyDollar = yyS[yypt-1 : yypt+1]
- //line query_string.y:39
+ //line query_string.y:40
{
logDebugGrammar("INPUT")
}
case 2:
yyDollar = yyS[yypt-2 : yypt+1]
- //line query_string.y:44
+ //line query_string.y:45
{
logDebugGrammar("SEARCH PARTS")
}
case 3:
yyDollar = yyS[yypt-1 : yypt+1]
- //line query_string.y:48
+ //line query_string.y:49
{
logDebugGrammar("SEARCH PART")
}
case 4:
yyDollar = yyS[yypt-3 : yypt+1]
- //line query_string.y:53
+ //line query_string.y:54
{
query := yyDollar[2].q
if yyDollar[3].pf != nil {
@@ -511,27 +512,27 @@ yydefault:
}
case 5:
yyDollar = yyS[yypt-0 : yypt+1]
- //line query_string.y:72
+ //line query_string.y:73
{
yyVAL.n = queryShould
}
case 6:
yyDollar = yyS[yypt-1 : yypt+1]
- //line query_string.y:76
+ //line query_string.y:77
{
logDebugGrammar("PLUS")
yyVAL.n = queryMust
}
case 7:
yyDollar = yyS[yypt-1 : yypt+1]
- //line query_string.y:81
+ //line query_string.y:82
{
logDebugGrammar("MINUS")
yyVAL.n = queryMustNot
}
case 8:
yyDollar = yyS[yypt-1 : yypt+1]
- //line query_string.y:87
+ //line query_string.y:88
{
str := yyDollar[1].s
logDebugGrammar("STRING - %s", str)
@@ -547,7 +548,7 @@ yydefault:
}
case 9:
yyDollar = yyS[yypt-2 : yypt+1]
- //line query_string.y:101
+ //line query_string.y:102
{
str := yyDollar[1].s
fuzziness, err := strconv.ParseFloat(yyDollar[2].s, 64)
@@ -561,7 +562,7 @@ yydefault:
}
case 10:
yyDollar = yyS[yypt-4 : yypt+1]
- //line query_string.y:113
+ //line query_string.y:114
{
field := yyDollar[1].s
str := yyDollar[3].s
@@ -577,16 +578,24 @@ yydefault:
}
case 11:
yyDollar = yyS[yypt-1 : yypt+1]
- //line query_string.y:127
+ //line query_string.y:128
{
str := yyDollar[1].s
logDebugGrammar("STRING - %s", str)
- q := NewMatchQuery(str)
+ q1 := NewMatchQuery(str)
+ val, err := strconv.ParseFloat(yyDollar[1].s, 64)
+ if err != nil {
+ yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("error parsing number: %v", err))
+ }
+ inclusive := true
+ q2 := NewNumericRangeInclusiveQuery(&val, &val, &inclusive, &inclusive)
+ q := NewDisjunctionQuery([]Query{q1, q2})
+ q.queryStringMode = true
yyVAL.q = q
}
case 12:
yyDollar = yyS[yypt-1 : yypt+1]
- //line query_string.y:134
+ //line query_string.y:143
{
phrase := yyDollar[1].s
logDebugGrammar("PHRASE - %s", phrase)
@@ -595,7 +604,7 @@ yydefault:
}
case 13:
yyDollar = yyS[yypt-3 : yypt+1]
- //line query_string.y:141
+ //line query_string.y:150
{
field := yyDollar[1].s
str := yyDollar[3].s
@@ -613,18 +622,27 @@ yydefault:
}
case 14:
yyDollar = yyS[yypt-3 : yypt+1]
- //line query_string.y:157
+ //line query_string.y:166
{
field := yyDollar[1].s
str := yyDollar[3].s
logDebugGrammar("FIELD - %s STRING - %s", field, str)
- q := NewMatchQuery(str)
- q.SetField(field)
+ q1 := NewMatchQuery(str)
+ q1.SetField(field)
+ val, err := strconv.ParseFloat(yyDollar[3].s, 64)
+ if err != nil {
+ yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("error parsing number: %v", err))
+ }
+ inclusive := true
+ q2 := NewNumericRangeInclusiveQuery(&val, &val, &inclusive, &inclusive)
+ q2.SetField(field)
+ q := NewDisjunctionQuery([]Query{q1, q2})
+ q.queryStringMode = true
yyVAL.q = q
}
case 15:
yyDollar = yyS[yypt-3 : yypt+1]
- //line query_string.y:166
+ //line query_string.y:184
{
field := yyDollar[1].s
phrase := yyDollar[3].s
@@ -635,10 +653,13 @@ yydefault:
}
case 16:
yyDollar = yyS[yypt-4 : yypt+1]
- //line query_string.y:175
+ //line query_string.y:193
{
field := yyDollar[1].s
- min, _ := strconv.ParseFloat(yyDollar[4].s, 64)
+ min, err := strconv.ParseFloat(yyDollar[4].s, 64)
+ if err != nil {
+ yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("error parsing number: %v", err))
+ }
minInclusive := false
logDebugGrammar("FIELD - GREATER THAN %f", min)
q := NewNumericRangeInclusiveQuery(&min, nil, &minInclusive, nil)
@@ -647,10 +668,13 @@ yydefault:
}
case 17:
yyDollar = yyS[yypt-5 : yypt+1]
- //line query_string.y:185
+ //line query_string.y:206
{
field := yyDollar[1].s
- min, _ := strconv.ParseFloat(yyDollar[5].s, 64)
+ min, err := strconv.ParseFloat(yyDollar[5].s, 64)
+ if err != nil {
+ yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("error parsing number: %v", err))
+ }
minInclusive := true
logDebugGrammar("FIELD - GREATER THAN OR EQUAL %f", min)
q := NewNumericRangeInclusiveQuery(&min, nil, &minInclusive, nil)
@@ -659,10 +683,13 @@ yydefault:
}
case 18:
yyDollar = yyS[yypt-4 : yypt+1]
- //line query_string.y:195
+ //line query_string.y:219
{
field := yyDollar[1].s
- max, _ := strconv.ParseFloat(yyDollar[4].s, 64)
+ max, err := strconv.ParseFloat(yyDollar[4].s, 64)
+ if err != nil {
+ yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("error parsing number: %v", err))
+ }
maxInclusive := false
logDebugGrammar("FIELD - LESS THAN %f", max)
q := NewNumericRangeInclusiveQuery(nil, &max, nil, &maxInclusive)
@@ -671,10 +698,13 @@ yydefault:
}
case 19:
yyDollar = yyS[yypt-5 : yypt+1]
- //line query_string.y:205
+ //line query_string.y:232
{
field := yyDollar[1].s
- max, _ := strconv.ParseFloat(yyDollar[5].s, 64)
+ max, err := strconv.ParseFloat(yyDollar[5].s, 64)
+ if err != nil {
+ yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("error parsing number: %v", err))
+ }
maxInclusive := true
logDebugGrammar("FIELD - LESS THAN OR EQUAL %f", max)
q := NewNumericRangeInclusiveQuery(nil, &max, nil, &maxInclusive)
@@ -683,7 +713,7 @@ yydefault:
}
case 20:
yyDollar = yyS[yypt-4 : yypt+1]
- //line query_string.y:215
+ //line query_string.y:245
{
field := yyDollar[1].s
minInclusive := false
@@ -700,7 +730,7 @@ yydefault:
}
case 21:
yyDollar = yyS[yypt-5 : yypt+1]
- //line query_string.y:230
+ //line query_string.y:260
{
field := yyDollar[1].s
minInclusive := true
@@ -717,7 +747,7 @@ yydefault:
}
case 22:
yyDollar = yyS[yypt-4 : yypt+1]
- //line query_string.y:245
+ //line query_string.y:275
{
field := yyDollar[1].s
maxInclusive := false
@@ -734,7 +764,7 @@ yydefault:
}
case 23:
yyDollar = yyS[yypt-5 : yypt+1]
- //line query_string.y:260
+ //line query_string.y:290
{
field := yyDollar[1].s
maxInclusive := true
@@ -751,13 +781,13 @@ yydefault:
}
case 24:
yyDollar = yyS[yypt-0 : yypt+1]
- //line query_string.y:276
+ //line query_string.y:306
{
yyVAL.pf = nil
}
case 25:
yyDollar = yyS[yypt-1 : yypt+1]
- //line query_string.y:280
+ //line query_string.y:310
{
yyVAL.pf = nil
boost, err := strconv.ParseFloat(yyDollar[1].s, 64)
@@ -768,6 +798,18 @@ yydefault:
}
logDebugGrammar("BOOST %f", boost)
}
+ case 26:
+ yyDollar = yyS[yypt-1 : yypt+1]
+ //line query_string.y:322
+ {
+ yyVAL.s = yyDollar[1].s
+ }
+ case 27:
+ yyDollar = yyS[yypt-2 : yypt+1]
+ //line query_string.y:326
+ {
+ yyVAL.s = "-" + yyDollar[2].s
+ }
}
goto yystack /* stack new state and value */
}
diff --git a/vendor/github.com/blevesearch/bleve/search/query/query_string_parser.go b/vendor/github.com/blevesearch/bleve/search/query/query_string_parser.go
index eb3b61e9ba..3fb7731b88 100644
--- a/vendor/github.com/blevesearch/bleve/search/query/query_string_parser.go
+++ b/vendor/github.com/blevesearch/bleve/search/query/query_string_parser.go
@@ -12,7 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-//go:generate go tool yacc -o query_string.y.go query_string.y
+// as of Go 1.8 this requires the goyacc external tool
+// available from golang.org/x/tools/cmd/goyacc
+
+//go:generate goyacc -o query_string.y.go query_string.y
//go:generate sed -i.tmp -e 1d query_string.y.go
//go:generate rm query_string.y.go.tmp
@@ -31,6 +34,9 @@ var debugParser bool
var debugLexer bool
func parseQuerySyntax(query string) (rq Query, err error) {
+ if query == "" {
+ return NewMatchNoneQuery(), nil
+ }
lex := newLexerWrapper(newQueryStringLex(strings.NewReader(query)))
doParse(lex)
@@ -66,7 +72,7 @@ type lexerWrapper struct {
func newLexerWrapper(lex yyLexer) *lexerWrapper {
return &lexerWrapper{
lex: lex,
- query: NewBooleanQuery(nil, nil, nil),
+ query: NewBooleanQueryForQueryString(nil, nil, nil),
}
}
diff --git a/vendor/github.com/blevesearch/bleve/search/query/regexp.go b/vendor/github.com/blevesearch/bleve/search/query/regexp.go
index 21d29b71d9..09544fcf1b 100644
--- a/vendor/github.com/blevesearch/bleve/search/query/regexp.go
+++ b/vendor/github.com/blevesearch/bleve/search/query/regexp.go
@@ -33,7 +33,9 @@ type RegexpQuery struct {
// NewRegexpQuery creates a new Query which finds
// documents containing terms that match the
-// specified regular expression.
+// specified regular expression. The regexp pattern
+// SHOULD NOT include ^ or $ modifiers, the search
+// will only match entire terms even without them.
func NewRegexpQuery(regexp string) *RegexpQuery {
return &RegexpQuery{
Regexp: regexp,
@@ -45,7 +47,7 @@ func (q *RegexpQuery) SetBoost(b float64) {
q.BoostVal = &boost
}
-func (q *RegexpQuery) Boost() float64{
+func (q *RegexpQuery) Boost() float64 {
return q.BoostVal.Value()
}
@@ -53,11 +55,11 @@ func (q *RegexpQuery) SetField(f string) {
q.FieldVal = f
}
-func (q *RegexpQuery) Field() string{
+func (q *RegexpQuery) Field() string {
return q.FieldVal
}
-func (q *RegexpQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
+func (q *RegexpQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, options search.SearcherOptions) (search.Searcher, error) {
field := q.FieldVal
if q.FieldVal == "" {
field = m.DefaultSearchField()
@@ -67,7 +69,7 @@ func (q *RegexpQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, expl
return nil, err
}
- return searcher.NewRegexpSearcher(i, q.compiled, field, q.BoostVal.Value(), explain)
+ return searcher.NewRegexpSearcher(i, q.compiled, field, q.BoostVal.Value(), options)
}
func (q *RegexpQuery) Validate() error {
@@ -76,14 +78,14 @@ func (q *RegexpQuery) Validate() error {
func (q *RegexpQuery) compile() error {
if q.compiled == nil {
- // require that pattern be anchored to start and end of term
+ // require that pattern NOT be anchored to start and end of term
actualRegexp := q.Regexp
- if !strings.HasPrefix(actualRegexp, "^") {
- actualRegexp = "^" + actualRegexp
- }
- if !strings.HasSuffix(actualRegexp, "$") {
- actualRegexp = actualRegexp + "$"
+ if strings.HasPrefix(actualRegexp, "^") {
+ actualRegexp = actualRegexp[1:] // remove leading ^
}
+ // do not attempt to remove trailing $, it's presence is not
+ // known to interfere with LiteralPrefix() the way ^ does
+ // and removing $ introduces possible ambiguities with escaped \$, \\$, etc
var err error
q.compiled, err = regexp.Compile(actualRegexp)
if err != nil {
diff --git a/vendor/github.com/blevesearch/bleve/search/query/term.go b/vendor/github.com/blevesearch/bleve/search/query/term.go
index 0e939ad32a..2eeb5a37a4 100644
--- a/vendor/github.com/blevesearch/bleve/search/query/term.go
+++ b/vendor/github.com/blevesearch/bleve/search/query/term.go
@@ -40,7 +40,7 @@ func (q *TermQuery) SetBoost(b float64) {
q.BoostVal = &boost
}
-func (q *TermQuery) Boost() float64{
+func (q *TermQuery) Boost() float64 {
return q.BoostVal.Value()
}
@@ -48,14 +48,14 @@ func (q *TermQuery) SetField(f string) {
q.FieldVal = f
}
-func (q *TermQuery) Field() string{
+func (q *TermQuery) Field() string {
return q.FieldVal
}
-func (q *TermQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
+func (q *TermQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, options search.SearcherOptions) (search.Searcher, error) {
field := q.FieldVal
if q.FieldVal == "" {
field = m.DefaultSearchField()
}
- return searcher.NewTermSearcher(i, q.Term, field, q.BoostVal.Value(), explain)
+ return searcher.NewTermSearcher(i, q.Term, field, q.BoostVal.Value(), options)
}
diff --git a/vendor/github.com/blevesearch/bleve/search/query/term_range.go b/vendor/github.com/blevesearch/bleve/search/query/term_range.go
new file mode 100644
index 0000000000..8f8ca8444f
--- /dev/null
+++ b/vendor/github.com/blevesearch/bleve/search/query/term_range.go
@@ -0,0 +1,95 @@
+// Copyright (c) 2017 Couchbase, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package query
+
+import (
+ "fmt"
+
+ "github.com/blevesearch/bleve/index"
+ "github.com/blevesearch/bleve/mapping"
+ "github.com/blevesearch/bleve/search"
+ "github.com/blevesearch/bleve/search/searcher"
+)
+
+type TermRangeQuery struct {
+ Min string `json:"min,omitempty"`
+ Max string `json:"max,omitempty"`
+ InclusiveMin *bool `json:"inclusive_min,omitempty"`
+ InclusiveMax *bool `json:"inclusive_max,omitempty"`
+ FieldVal string `json:"field,omitempty"`
+ BoostVal *Boost `json:"boost,omitempty"`
+}
+
+// NewTermRangeQuery creates a new Query for ranges
+// of text term values.
+// Either, but not both endpoints can be nil.
+// The minimum value is inclusive.
+// The maximum value is exclusive.
+func NewTermRangeQuery(min, max string) *TermRangeQuery {
+ return NewTermRangeInclusiveQuery(min, max, nil, nil)
+}
+
+// NewTermRangeInclusiveQuery creates a new Query for ranges
+// of numeric values.
+// Either, but not both endpoints can be nil.
+// Control endpoint inclusion with inclusiveMin, inclusiveMax.
+func NewTermRangeInclusiveQuery(min, max string, minInclusive, maxInclusive *bool) *TermRangeQuery {
+ return &TermRangeQuery{
+ Min: min,
+ Max: max,
+ InclusiveMin: minInclusive,
+ InclusiveMax: maxInclusive,
+ }
+}
+
+func (q *TermRangeQuery) SetBoost(b float64) {
+ boost := Boost(b)
+ q.BoostVal = &boost
+}
+
+func (q *TermRangeQuery) Boost() float64 {
+ return q.BoostVal.Value()
+}
+
+func (q *TermRangeQuery) SetField(f string) {
+ q.FieldVal = f
+}
+
+func (q *TermRangeQuery) Field() string {
+ return q.FieldVal
+}
+
+func (q *TermRangeQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, options search.SearcherOptions) (search.Searcher, error) {
+ field := q.FieldVal
+ if q.FieldVal == "" {
+ field = m.DefaultSearchField()
+ }
+ var minTerm []byte
+ if q.Min != "" {
+ minTerm = []byte(q.Min)
+ }
+ var maxTerm []byte
+ if q.Max != "" {
+ maxTerm = []byte(q.Max)
+ }
+ return searcher.NewTermRangeSearcher(i, minTerm, maxTerm, q.InclusiveMin, q.InclusiveMax, field, q.BoostVal.Value(), options)
+}
+
+func (q *TermRangeQuery) Validate() error {
+ if q.Min == "" && q.Min == q.Max {
+ return fmt.Errorf("term range query must specify min or max")
+ }
+ return nil
+}
diff --git a/vendor/github.com/blevesearch/bleve/search/query/wildcard.go b/vendor/github.com/blevesearch/bleve/search/query/wildcard.go
index 51a8cdef18..7fd7482c4d 100644
--- a/vendor/github.com/blevesearch/bleve/search/query/wildcard.go
+++ b/vendor/github.com/blevesearch/bleve/search/query/wildcard.go
@@ -66,7 +66,7 @@ func (q *WildcardQuery) SetBoost(b float64) {
q.BoostVal = &boost
}
-func (q *WildcardQuery) Boost() float64{
+func (q *WildcardQuery) Boost() float64 {
return q.BoostVal.Value()
}
@@ -74,11 +74,11 @@ func (q *WildcardQuery) SetField(f string) {
q.FieldVal = f
}
-func (q *WildcardQuery) Field() string{
+func (q *WildcardQuery) Field() string {
return q.FieldVal
}
-func (q *WildcardQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
+func (q *WildcardQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, options search.SearcherOptions) (search.Searcher, error) {
field := q.FieldVal
if q.FieldVal == "" {
field = m.DefaultSearchField()
@@ -91,7 +91,7 @@ func (q *WildcardQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, ex
}
}
- return searcher.NewRegexpSearcher(i, q.compiled, field, q.BoostVal.Value(), explain)
+ return searcher.NewRegexpSearcher(i, q.compiled, field, q.BoostVal.Value(), options)
}
func (q *WildcardQuery) Validate() error {
@@ -101,6 +101,6 @@ func (q *WildcardQuery) Validate() error {
}
func (q *WildcardQuery) convertToRegexp() (*regexp.Regexp, error) {
- regexpString := "^" + wildcardRegexpReplacer.Replace(q.Wildcard) + "$"
+ regexpString := wildcardRegexpReplacer.Replace(q.Wildcard)
return regexp.Compile(regexpString)
}
diff --git a/vendor/github.com/blevesearch/bleve/search/scorer/scorer_conjunction.go b/vendor/github.com/blevesearch/bleve/search/scorer/scorer_conjunction.go
index 0042f73ff4..aad6f9c160 100644
--- a/vendor/github.com/blevesearch/bleve/search/scorer/scorer_conjunction.go
+++ b/vendor/github.com/blevesearch/bleve/search/scorer/scorer_conjunction.go
@@ -19,26 +19,26 @@ import (
)
type ConjunctionQueryScorer struct {
- explain bool
+ options search.SearcherOptions
}
-func NewConjunctionQueryScorer(explain bool) *ConjunctionQueryScorer {
+func NewConjunctionQueryScorer(options search.SearcherOptions) *ConjunctionQueryScorer {
return &ConjunctionQueryScorer{
- explain: explain,
+ options: options,
}
}
func (s *ConjunctionQueryScorer) Score(ctx *search.SearchContext, constituents []*search.DocumentMatch) *search.DocumentMatch {
var sum float64
var childrenExplanations []*search.Explanation
- if s.explain {
+ if s.options.Explain {
childrenExplanations = make([]*search.Explanation, len(constituents))
}
locations := []search.FieldTermLocationMap{}
for i, docMatch := range constituents {
sum += docMatch.Score
- if s.explain {
+ if s.options.Explain {
childrenExplanations[i] = docMatch.Expl
}
if docMatch.Locations != nil {
@@ -47,7 +47,7 @@ func (s *ConjunctionQueryScorer) Score(ctx *search.SearchContext, constituents [
}
newScore := sum
var newExpl *search.Explanation
- if s.explain {
+ if s.options.Explain {
newExpl = &search.Explanation{Value: sum, Message: "sum of:", Children: childrenExplanations}
}
diff --git a/vendor/github.com/blevesearch/bleve/search/scorer/scorer_constant.go b/vendor/github.com/blevesearch/bleve/search/scorer/scorer_constant.go
index dcaba2b17d..a65a826f2d 100644
--- a/vendor/github.com/blevesearch/bleve/search/scorer/scorer_constant.go
+++ b/vendor/github.com/blevesearch/bleve/search/scorer/scorer_constant.go
@@ -24,15 +24,15 @@ import (
type ConstantScorer struct {
constant float64
boost float64
- explain bool
+ options search.SearcherOptions
queryNorm float64
queryWeight float64
queryWeightExplanation *search.Explanation
}
-func NewConstantScorer(constant float64, boost float64, explain bool) *ConstantScorer {
+func NewConstantScorer(constant float64, boost float64, options search.SearcherOptions) *ConstantScorer {
rv := ConstantScorer{
- explain: explain,
+ options: options,
queryWeight: 1.0,
constant: constant,
boost: boost,
@@ -52,7 +52,7 @@ func (s *ConstantScorer) SetQueryNorm(qnorm float64) {
// update the query weight
s.queryWeight = s.boost * s.queryNorm
- if s.explain {
+ if s.options.Explain {
childrenExplanations := make([]*search.Explanation, 2)
childrenExplanations[0] = &search.Explanation{
Value: s.boost,
@@ -75,7 +75,7 @@ func (s *ConstantScorer) Score(ctx *search.SearchContext, id index.IndexInternal
score := s.constant
- if s.explain {
+ if s.options.Explain {
scoreExplanation = &search.Explanation{
Value: score,
Message: fmt.Sprintf("ConstantScore()"),
@@ -85,7 +85,7 @@ func (s *ConstantScorer) Score(ctx *search.SearchContext, id index.IndexInternal
// if the query weight isn't 1, multiply
if s.queryWeight != 1.0 {
score = score * s.queryWeight
- if s.explain {
+ if s.options.Explain {
childExplanations := make([]*search.Explanation, 2)
childExplanations[0] = s.queryWeightExplanation
childExplanations[1] = scoreExplanation
@@ -100,7 +100,7 @@ func (s *ConstantScorer) Score(ctx *search.SearchContext, id index.IndexInternal
rv := ctx.DocumentMatchPool.Get()
rv.IndexInternalID = id
rv.Score = score
- if s.explain {
+ if s.options.Explain {
rv.Expl = scoreExplanation
}
diff --git a/vendor/github.com/blevesearch/bleve/search/scorer/scorer_disjunction.go b/vendor/github.com/blevesearch/bleve/search/scorer/scorer_disjunction.go
index 30cbac2f5d..184a15d276 100644
--- a/vendor/github.com/blevesearch/bleve/search/scorer/scorer_disjunction.go
+++ b/vendor/github.com/blevesearch/bleve/search/scorer/scorer_disjunction.go
@@ -21,26 +21,26 @@ import (
)
type DisjunctionQueryScorer struct {
- explain bool
+ options search.SearcherOptions
}
-func NewDisjunctionQueryScorer(explain bool) *DisjunctionQueryScorer {
+func NewDisjunctionQueryScorer(options search.SearcherOptions) *DisjunctionQueryScorer {
return &DisjunctionQueryScorer{
- explain: explain,
+ options: options,
}
}
func (s *DisjunctionQueryScorer) Score(ctx *search.SearchContext, constituents []*search.DocumentMatch, countMatch, countTotal int) *search.DocumentMatch {
var sum float64
var childrenExplanations []*search.Explanation
- if s.explain {
+ if s.options.Explain {
childrenExplanations = make([]*search.Explanation, len(constituents))
}
var locations []search.FieldTermLocationMap
for i, docMatch := range constituents {
sum += docMatch.Score
- if s.explain {
+ if s.options.Explain {
childrenExplanations[i] = docMatch.Expl
}
if docMatch.Locations != nil {
@@ -49,14 +49,14 @@ func (s *DisjunctionQueryScorer) Score(ctx *search.SearchContext, constituents [
}
var rawExpl *search.Explanation
- if s.explain {
+ if s.options.Explain {
rawExpl = &search.Explanation{Value: sum, Message: "sum of:", Children: childrenExplanations}
}
coord := float64(countMatch) / float64(countTotal)
newScore := sum * coord
var newExpl *search.Explanation
- if s.explain {
+ if s.options.Explain {
ce := make([]*search.Explanation, 2)
ce[0] = rawExpl
ce[1] = &search.Explanation{Value: coord, Message: fmt.Sprintf("coord(%d/%d)", countMatch, countTotal)}
diff --git a/vendor/github.com/blevesearch/bleve/search/scorer/scorer_term.go b/vendor/github.com/blevesearch/bleve/search/scorer/scorer_term.go
index 3a5b1be4d6..b5f46322ca 100644
--- a/vendor/github.com/blevesearch/bleve/search/scorer/scorer_term.go
+++ b/vendor/github.com/blevesearch/bleve/search/scorer/scorer_term.go
@@ -23,20 +23,20 @@ import (
)
type TermQueryScorer struct {
- queryTerm string
+ queryTerm []byte
queryField string
queryBoost float64
docTerm uint64
docTotal uint64
idf float64
- explain bool
+ options search.SearcherOptions
idfExplanation *search.Explanation
queryNorm float64
queryWeight float64
queryWeightExplanation *search.Explanation
}
-func NewTermQueryScorer(queryTerm string, queryField string, queryBoost float64, docTotal, docTerm uint64, explain bool) *TermQueryScorer {
+func NewTermQueryScorer(queryTerm []byte, queryField string, queryBoost float64, docTotal, docTerm uint64, options search.SearcherOptions) *TermQueryScorer {
rv := TermQueryScorer{
queryTerm: queryTerm,
queryField: queryField,
@@ -44,11 +44,11 @@ func NewTermQueryScorer(queryTerm string, queryField string, queryBoost float64,
docTerm: docTerm,
docTotal: docTotal,
idf: 1.0 + math.Log(float64(docTotal)/float64(docTerm+1.0)),
- explain: explain,
+ options: options,
queryWeight: 1.0,
}
- if explain {
+ if options.Explain {
rv.idfExplanation = &search.Explanation{
Value: rv.idf,
Message: fmt.Sprintf("idf(docFreq=%d, maxDocs=%d)", docTerm, docTotal),
@@ -69,7 +69,7 @@ func (s *TermQueryScorer) SetQueryNorm(qnorm float64) {
// update the query weight
s.queryWeight = s.queryBoost * s.idf * s.queryNorm
- if s.explain {
+ if s.options.Explain {
childrenExplanations := make([]*search.Explanation, 3)
childrenExplanations[0] = &search.Explanation{
Value: s.queryBoost,
@@ -100,7 +100,7 @@ func (s *TermQueryScorer) Score(ctx *search.SearchContext, termMatch *index.Term
}
score := tf * termMatch.Norm * s.idf
- if s.explain {
+ if s.options.Explain {
childrenExplanations := make([]*search.Explanation, 3)
childrenExplanations[0] = &search.Explanation{
Value: tf,
@@ -121,7 +121,7 @@ func (s *TermQueryScorer) Score(ctx *search.SearchContext, termMatch *index.Term
// if the query weight isn't 1, multiply
if s.queryWeight != 1.0 {
score = score * s.queryWeight
- if s.explain {
+ if s.options.Explain {
childExplanations := make([]*search.Explanation, 2)
childExplanations[0] = s.queryWeightExplanation
childExplanations[1] = scoreExplanation
@@ -136,44 +136,46 @@ func (s *TermQueryScorer) Score(ctx *search.SearchContext, termMatch *index.Term
rv := ctx.DocumentMatchPool.Get()
rv.IndexInternalID = append(rv.IndexInternalID, termMatch.ID...)
rv.Score = score
- if s.explain {
+ if s.options.Explain {
rv.Expl = scoreExplanation
}
if termMatch.Vectors != nil && len(termMatch.Vectors) > 0 {
+ locs := make([]search.Location, len(termMatch.Vectors))
+ locsUsed := 0
+
+ totalPositions := 0
+ for _, v := range termMatch.Vectors {
+ totalPositions += len(v.ArrayPositions)
+ }
+ positions := make(search.ArrayPositions, totalPositions)
+ positionsUsed := 0
rv.Locations = make(search.FieldTermLocationMap)
for _, v := range termMatch.Vectors {
tlm := rv.Locations[v.Field]
if tlm == nil {
tlm = make(search.TermLocationMap)
+ rv.Locations[v.Field] = tlm
}
- loc := search.Location{
- Pos: float64(v.Pos),
- Start: float64(v.Start),
- End: float64(v.End),
- }
+ loc := &locs[locsUsed]
+ locsUsed++
+
+ loc.Pos = v.Pos
+ loc.Start = v.Start
+ loc.End = v.End
if len(v.ArrayPositions) > 0 {
- loc.ArrayPositions = make([]float64, len(v.ArrayPositions))
+ loc.ArrayPositions = positions[positionsUsed : positionsUsed+len(v.ArrayPositions)]
for i, ap := range v.ArrayPositions {
- loc.ArrayPositions[i] = float64(ap)
+ loc.ArrayPositions[i] = ap
}
+ positionsUsed += len(v.ArrayPositions)
}
- locations := tlm[s.queryTerm]
- if locations == nil {
- locations = make(search.Locations, 1)
- locations[0] = &loc
- } else {
- locations = append(locations, &loc)
- }
- tlm[s.queryTerm] = locations
-
- rv.Locations[v.Field] = tlm
+ tlm[string(s.queryTerm)] = append(tlm[string(s.queryTerm)], loc)
}
-
}
return rv
diff --git a/vendor/github.com/blevesearch/bleve/search/search.go b/vendor/github.com/blevesearch/bleve/search/search.go
index e3e0a5b694..cbbcfbfd66 100644
--- a/vendor/github.com/blevesearch/bleve/search/search.go
+++ b/vendor/github.com/blevesearch/bleve/search/search.go
@@ -21,27 +21,32 @@ import (
"github.com/blevesearch/bleve/index"
)
-type Location struct {
- Pos float64 `json:"pos"`
- Start float64 `json:"start"`
- End float64 `json:"end"`
- ArrayPositions []float64 `json:"array_positions"`
-}
+type ArrayPositions []uint64
-// SameArrayElement returns true if two locations are point to
-// the same array element
-func (l *Location) SameArrayElement(other *Location) bool {
- if len(l.ArrayPositions) != len(other.ArrayPositions) {
+func (ap ArrayPositions) Equals(other ArrayPositions) bool {
+ if len(ap) != len(other) {
return false
}
- for i, elem := range l.ArrayPositions {
- if other.ArrayPositions[i] != elem {
+ for i := range ap {
+ if ap[i] != other[i] {
return false
}
}
return true
}
+type Location struct {
+ // Pos is the position of the term within the field, starting at 1
+ Pos uint64 `json:"pos"`
+
+ // Start and End are the byte offsets of the term in the field
+ Start uint64 `json:"start"`
+ End uint64 `json:"end"`
+
+ // ArrayPositions contains the positions of the term within any elements.
+ ArrayPositions ArrayPositions `json:"array_positions"`
+}
+
type Locations []*Location
type TermLocationMap map[string]Locations
@@ -69,10 +74,6 @@ type DocumentMatch struct {
// fields as float64s and date fields as time.RFC3339 formatted strings.
Fields map[string]interface{} `json:"fields,omitempty"`
- // as we learn field terms, we can cache important ones for later use
- // for example, sorting and building facets need these values
- CachedFieldTerms index.FieldTerms `json:"-"`
-
// if we load the document for this hit, remember it so we dont load again
Document *document.Document `json:"-"`
@@ -138,6 +139,11 @@ type Searcher interface {
DocumentMatchPoolSize() int
}
+type SearcherOptions struct {
+ Explain bool
+ IncludeTermVectors bool
+}
+
// SearchContext represents the context around a single search
type SearchContext struct {
DocumentMatchPool *DocumentMatchPool
diff --git a/vendor/github.com/blevesearch/bleve/search/searcher/search_boolean.go b/vendor/github.com/blevesearch/bleve/search/searcher/search_boolean.go
index 4dbd604bc7..a905c29e50 100644
--- a/vendor/github.com/blevesearch/bleve/search/searcher/search_boolean.go
+++ b/vendor/github.com/blevesearch/bleve/search/searcher/search_boolean.go
@@ -38,14 +38,14 @@ type BooleanSearcher struct {
initialized bool
}
-func NewBooleanSearcher(indexReader index.IndexReader, mustSearcher search.Searcher, shouldSearcher search.Searcher, mustNotSearcher search.Searcher, explain bool) (*BooleanSearcher, error) {
+func NewBooleanSearcher(indexReader index.IndexReader, mustSearcher search.Searcher, shouldSearcher search.Searcher, mustNotSearcher search.Searcher, options search.SearcherOptions) (*BooleanSearcher, error) {
// build our searcher
rv := BooleanSearcher{
indexReader: indexReader,
mustSearcher: mustSearcher,
shouldSearcher: shouldSearcher,
mustNotSearcher: mustNotSearcher,
- scorer: scorer.NewConjunctionQueryScorer(explain),
+ scorer: scorer.NewConjunctionQueryScorer(options),
matches: make([]*search.DocumentMatch, 2),
}
rv.computeQueryNorm()
diff --git a/vendor/github.com/blevesearch/bleve/search/searcher/search_conjunction.go b/vendor/github.com/blevesearch/bleve/search/searcher/search_conjunction.go
index 7ec0d2837e..9ab0e7fa4c 100644
--- a/vendor/github.com/blevesearch/bleve/search/searcher/search_conjunction.go
+++ b/vendor/github.com/blevesearch/bleve/search/searcher/search_conjunction.go
@@ -31,10 +31,10 @@ type ConjunctionSearcher struct {
maxIDIdx int
scorer *scorer.ConjunctionQueryScorer
initialized bool
- explain bool
+ options search.SearcherOptions
}
-func NewConjunctionSearcher(indexReader index.IndexReader, qsearchers []search.Searcher, explain bool) (*ConjunctionSearcher, error) {
+func NewConjunctionSearcher(indexReader index.IndexReader, qsearchers []search.Searcher, options search.SearcherOptions) (*ConjunctionSearcher, error) {
// build the downstream searchers
searchers := make(OrderedSearcherList, len(qsearchers))
for i, searcher := range qsearchers {
@@ -45,10 +45,10 @@ func NewConjunctionSearcher(indexReader index.IndexReader, qsearchers []search.S
// build our searcher
rv := ConjunctionSearcher{
indexReader: indexReader,
- explain: explain,
+ options: options,
searchers: searchers,
currs: make([]*search.DocumentMatch, len(searchers)),
- scorer: scorer.NewConjunctionQueryScorer(explain),
+ scorer: scorer.NewConjunctionQueryScorer(options),
}
rv.computeQueryNorm()
return &rv, nil
diff --git a/vendor/github.com/blevesearch/bleve/search/searcher/search_disjunction.go b/vendor/github.com/blevesearch/bleve/search/searcher/search_disjunction.go
index 1d08803adf..96bd544747 100644
--- a/vendor/github.com/blevesearch/bleve/search/searcher/search_disjunction.go
+++ b/vendor/github.com/blevesearch/bleve/search/searcher/search_disjunction.go
@@ -50,11 +50,22 @@ func tooManyClauses(count int) bool {
}
func tooManyClausesErr() error {
- return fmt.Errorf("TooManyClauses[maxClauseCount is set to %d]", DisjunctionMaxClauseCount)
+ return fmt.Errorf("TooManyClauses[maxClauseCount is set to %d]",
+ DisjunctionMaxClauseCount)
}
-func NewDisjunctionSearcher(indexReader index.IndexReader, qsearchers []search.Searcher, min float64, explain bool) (*DisjunctionSearcher, error) {
- if tooManyClauses(len(qsearchers)) {
+func NewDisjunctionSearcher(indexReader index.IndexReader,
+ qsearchers []search.Searcher, min float64, options search.SearcherOptions) (
+ *DisjunctionSearcher, error) {
+ return newDisjunctionSearcher(indexReader, qsearchers, min, options,
+ true)
+}
+
+func newDisjunctionSearcher(indexReader index.IndexReader,
+ qsearchers []search.Searcher, min float64, options search.SearcherOptions,
+ limit bool) (
+ *DisjunctionSearcher, error) {
+ if limit && tooManyClauses(len(qsearchers)) {
return nil, tooManyClausesErr()
}
// build the downstream searchers
@@ -70,7 +81,7 @@ func NewDisjunctionSearcher(indexReader index.IndexReader, qsearchers []search.S
searchers: searchers,
numSearchers: len(searchers),
currs: make([]*search.DocumentMatch, len(searchers)),
- scorer: scorer.NewDisjunctionQueryScorer(explain),
+ scorer: scorer.NewDisjunctionQueryScorer(options),
min: int(min),
matching: make([]*search.DocumentMatch, len(searchers)),
matchingIdxs: make([]int, len(searchers)),
@@ -161,7 +172,8 @@ func (s *DisjunctionSearcher) SetQueryNorm(qnorm float64) {
}
}
-func (s *DisjunctionSearcher) Next(ctx *search.SearchContext) (*search.DocumentMatch, error) {
+func (s *DisjunctionSearcher) Next(ctx *search.SearchContext) (
+ *search.DocumentMatch, error) {
if !s.initialized {
err := s.initSearchers(ctx)
if err != nil {
@@ -199,7 +211,8 @@ func (s *DisjunctionSearcher) Next(ctx *search.SearchContext) (*search.DocumentM
return rv, nil
}
-func (s *DisjunctionSearcher) Advance(ctx *search.SearchContext, ID index.IndexInternalID) (*search.DocumentMatch, error) {
+func (s *DisjunctionSearcher) Advance(ctx *search.SearchContext,
+ ID index.IndexInternalID) (*search.DocumentMatch, error) {
if !s.initialized {
err := s.initSearchers(ctx)
if err != nil {
diff --git a/vendor/github.com/blevesearch/bleve/search/searcher/search_docid.go b/vendor/github.com/blevesearch/bleve/search/searcher/search_docid.go
index d0794823b0..06351b4a0d 100644
--- a/vendor/github.com/blevesearch/bleve/search/searcher/search_docid.go
+++ b/vendor/github.com/blevesearch/bleve/search/searcher/search_docid.go
@@ -28,13 +28,13 @@ type DocIDSearcher struct {
}
func NewDocIDSearcher(indexReader index.IndexReader, ids []string, boost float64,
- explain bool) (searcher *DocIDSearcher, err error) {
+ options search.SearcherOptions) (searcher *DocIDSearcher, err error) {
reader, err := indexReader.DocIDReaderOnly(ids)
if err != nil {
return nil, err
}
- scorer := scorer.NewConstantScorer(1.0, boost, explain)
+ scorer := scorer.NewConstantScorer(1.0, boost, options)
return &DocIDSearcher{
scorer: scorer,
reader: reader,
diff --git a/vendor/github.com/blevesearch/bleve/search/searcher/search_filter.go b/vendor/github.com/blevesearch/bleve/search/searcher/search_filter.go
new file mode 100644
index 0000000000..219f2ee7eb
--- /dev/null
+++ b/vendor/github.com/blevesearch/bleve/search/searcher/search_filter.go
@@ -0,0 +1,88 @@
+// Copyright (c) 2017 Couchbase, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package searcher
+
+import (
+ "github.com/blevesearch/bleve/index"
+ "github.com/blevesearch/bleve/search"
+)
+
+// FilterFunc defines a function which can filter documents
+// returning true means keep the document
+// returning false means do not keep the document
+type FilterFunc func(d *search.DocumentMatch) bool
+
+// FilteringSearcher wraps any other searcher, but checks any Next/Advance
+// call against the supplied FilterFunc
+type FilteringSearcher struct {
+ child search.Searcher
+ accept FilterFunc
+}
+
+func NewFilteringSearcher(s search.Searcher, filter FilterFunc) *FilteringSearcher {
+ return &FilteringSearcher{
+ child: s,
+ accept: filter,
+ }
+}
+
+func (f *FilteringSearcher) Next(ctx *search.SearchContext) (*search.DocumentMatch, error) {
+ next, err := f.child.Next(ctx)
+ for next != nil && err == nil {
+ if f.accept(next) {
+ return next, nil
+ }
+ next, err = f.child.Next(ctx)
+ }
+ return nil, err
+}
+
+func (f *FilteringSearcher) Advance(ctx *search.SearchContext, ID index.IndexInternalID) (*search.DocumentMatch, error) {
+ adv, err := f.child.Advance(ctx, ID)
+ if err != nil {
+ return nil, err
+ }
+ if adv == nil {
+ return nil, nil
+ }
+ if f.accept(adv) {
+ return adv, nil
+ }
+ return f.Next(ctx)
+}
+
+func (f *FilteringSearcher) Close() error {
+ return f.child.Close()
+}
+
+func (f *FilteringSearcher) Weight() float64 {
+ return f.child.Weight()
+}
+
+func (f *FilteringSearcher) SetQueryNorm(n float64) {
+ f.child.SetQueryNorm(n)
+}
+
+func (f *FilteringSearcher) Count() uint64 {
+ return f.child.Count()
+}
+
+func (f *FilteringSearcher) Min() int {
+ return f.child.Min()
+}
+
+func (f *FilteringSearcher) DocumentMatchPoolSize() int {
+ return f.child.DocumentMatchPoolSize()
+}
diff --git a/vendor/github.com/blevesearch/bleve/search/searcher/search_fuzzy.go b/vendor/github.com/blevesearch/bleve/search/searcher/search_fuzzy.go
index c8c405828c..90abaa0a85 100644
--- a/vendor/github.com/blevesearch/bleve/search/searcher/search_fuzzy.go
+++ b/vendor/github.com/blevesearch/bleve/search/searcher/search_fuzzy.go
@@ -19,17 +19,9 @@ import (
"github.com/blevesearch/bleve/search"
)
-type FuzzySearcher struct {
- indexReader index.IndexReader
- term string
- prefix int
- fuzziness int
- field string
- explain bool
- searcher *DisjunctionSearcher
-}
-
-func NewFuzzySearcher(indexReader index.IndexReader, term string, prefix, fuzziness int, field string, boost float64, explain bool) (*FuzzySearcher, error) {
+func NewFuzzySearcher(indexReader index.IndexReader, term string,
+ prefix, fuzziness int, field string, boost float64,
+ options search.SearcherOptions) (search.Searcher, error) {
// Note: we don't byte slice the term for a prefix because of runes.
prefixTerm := ""
for i, r := range term {
@@ -40,46 +32,18 @@ func NewFuzzySearcher(indexReader index.IndexReader, term string, prefix, fuzzin
}
}
- candidateTerms, err := findFuzzyCandidateTerms(indexReader, term, fuzziness, field, prefixTerm)
- if err != nil {
- return nil, err
- }
-
- // enumerate all the terms in the range
- qsearchers := make([]search.Searcher, 0, len(candidateTerms))
- qsearchersClose := func() {
- for _, searcher := range qsearchers {
- _ = searcher.Close()
- }
- }
- for _, cterm := range candidateTerms {
- qsearcher, err := NewTermSearcher(indexReader, cterm, field, boost, explain)
- if err != nil {
- qsearchersClose()
- return nil, err
- }
- qsearchers = append(qsearchers, qsearcher)
- }
-
- // build disjunction searcher of these ranges
- searcher, err := NewDisjunctionSearcher(indexReader, qsearchers, 0, explain)
+ candidateTerms, err := findFuzzyCandidateTerms(indexReader, term, fuzziness,
+ field, prefixTerm)
if err != nil {
- qsearchersClose()
return nil, err
}
- return &FuzzySearcher{
- indexReader: indexReader,
- term: term,
- prefix: prefix,
- fuzziness: fuzziness,
- field: field,
- explain: explain,
- searcher: searcher,
- }, nil
+ return NewMultiTermSearcher(indexReader, candidateTerms, field,
+ boost, options, true)
}
-func findFuzzyCandidateTerms(indexReader index.IndexReader, term string, fuzziness int, field, prefixTerm string) (rv []string, err error) {
+func findFuzzyCandidateTerms(indexReader index.IndexReader, term string,
+ fuzziness int, field, prefixTerm string) (rv []string, err error) {
rv = make([]string, 0)
var fieldDict index.FieldDict
if len(prefixTerm) > 0 {
@@ -108,36 +72,3 @@ func findFuzzyCandidateTerms(indexReader index.IndexReader, term string, fuzzine
return rv, err
}
-
-func (s *FuzzySearcher) Count() uint64 {
- return s.searcher.Count()
-}
-
-func (s *FuzzySearcher) Weight() float64 {
- return s.searcher.Weight()
-}
-
-func (s *FuzzySearcher) SetQueryNorm(qnorm float64) {
- s.searcher.SetQueryNorm(qnorm)
-}
-
-func (s *FuzzySearcher) Next(ctx *search.SearchContext) (*search.DocumentMatch, error) {
- return s.searcher.Next(ctx)
-
-}
-
-func (s *FuzzySearcher) Advance(ctx *search.SearchContext, ID index.IndexInternalID) (*search.DocumentMatch, error) {
- return s.searcher.Advance(ctx, ID)
-}
-
-func (s *FuzzySearcher) Close() error {
- return s.searcher.Close()
-}
-
-func (s *FuzzySearcher) Min() int {
- return 0
-}
-
-func (s *FuzzySearcher) DocumentMatchPoolSize() int {
- return s.searcher.DocumentMatchPoolSize()
-}
diff --git a/vendor/github.com/blevesearch/bleve/search/searcher/search_geoboundingbox.go b/vendor/github.com/blevesearch/bleve/search/searcher/search_geoboundingbox.go
new file mode 100644
index 0000000000..f8b1b4cf7a
--- /dev/null
+++ b/vendor/github.com/blevesearch/bleve/search/searcher/search_geoboundingbox.go
@@ -0,0 +1,173 @@
+// Copyright (c) 2017 Couchbase, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package searcher
+
+import (
+ "github.com/blevesearch/bleve/document"
+ "github.com/blevesearch/bleve/geo"
+ "github.com/blevesearch/bleve/index"
+ "github.com/blevesearch/bleve/numeric"
+ "github.com/blevesearch/bleve/search"
+)
+
+func NewGeoBoundingBoxSearcher(indexReader index.IndexReader, minLon, minLat,
+ maxLon, maxLat float64, field string, boost float64,
+ options search.SearcherOptions, checkBoundaries bool) (
+ search.Searcher, error) {
+
+ // track list of opened searchers, for cleanup on early exit
+ var openedSearchers []search.Searcher
+ cleanupOpenedSearchers := func() {
+ for _, s := range openedSearchers {
+ _ = s.Close()
+ }
+ }
+
+ // do math to produce list of terms needed for this search
+ onBoundaryTerms, notOnBoundaryTerms := ComputeGeoRange(0, (geo.GeoBits<<1)-1,
+ minLon, minLat, maxLon, maxLat, checkBoundaries)
+
+ var onBoundarySearcher search.Searcher
+ if len(onBoundaryTerms) > 0 {
+ rawOnBoundarySearcher, err := NewMultiTermSearcherBytes(indexReader,
+ onBoundaryTerms, field, boost, options, false)
+ if err != nil {
+ return nil, err
+ }
+ // add filter to check points near the boundary
+ onBoundarySearcher = NewFilteringSearcher(rawOnBoundarySearcher,
+ buildRectFilter(indexReader, field, minLon, minLat, maxLon, maxLat))
+ openedSearchers = append(openedSearchers, onBoundarySearcher)
+ }
+
+ var notOnBoundarySearcher search.Searcher
+ if len(notOnBoundaryTerms) > 0 {
+ var err error
+ notOnBoundarySearcher, err = NewMultiTermSearcherBytes(indexReader,
+ notOnBoundaryTerms, field, boost, options, false)
+ if err != nil {
+ cleanupOpenedSearchers()
+ return nil, err
+ }
+ openedSearchers = append(openedSearchers, notOnBoundarySearcher)
+ }
+
+ if onBoundarySearcher != nil && notOnBoundarySearcher != nil {
+ rv, err := NewDisjunctionSearcher(indexReader,
+ []search.Searcher{
+ onBoundarySearcher,
+ notOnBoundarySearcher,
+ },
+ 0, options)
+ if err != nil {
+ cleanupOpenedSearchers()
+ return nil, err
+ }
+ return rv, nil
+ } else if onBoundarySearcher != nil {
+ return onBoundarySearcher, nil
+ } else if notOnBoundarySearcher != nil {
+ return notOnBoundarySearcher, nil
+ }
+
+ return NewMatchNoneSearcher(indexReader)
+}
+
+var geoMaxShift = document.GeoPrecisionStep * 4
+var geoDetailLevel = ((geo.GeoBits << 1) - geoMaxShift) / 2
+
+func ComputeGeoRange(term uint64, shift uint,
+ sminLon, sminLat, smaxLon, smaxLat float64,
+ checkBoundaries bool) (
+ onBoundary [][]byte, notOnBoundary [][]byte) {
+ split := term | uint64(0x1)<<shift
+ var upperMax uint64
+ if shift < 63 {
+ upperMax = term | ((uint64(1) << (shift + 1)) - 1)
+ } else {
+ upperMax = 0xffffffffffffffff
+ }
+ lowerMax := split - 1
+ onBoundary, notOnBoundary = relateAndRecurse(term, lowerMax, shift,
+ sminLon, sminLat, smaxLon, smaxLat, checkBoundaries)
+ plusOnBoundary, plusNotOnBoundary := relateAndRecurse(split, upperMax, shift,
+ sminLon, sminLat, smaxLon, smaxLat, checkBoundaries)
+ onBoundary = append(onBoundary, plusOnBoundary...)
+ notOnBoundary = append(notOnBoundary, plusNotOnBoundary...)
+ return
+}
+
+func relateAndRecurse(start, end uint64, res uint,
+ sminLon, sminLat, smaxLon, smaxLat float64,
+ checkBoundaries bool) (
+ onBoundary [][]byte, notOnBoundary [][]byte) {
+ minLon := geo.MortonUnhashLon(start)
+ minLat := geo.MortonUnhashLat(start)
+ maxLon := geo.MortonUnhashLon(end)
+ maxLat := geo.MortonUnhashLat(end)
+
+ level := ((geo.GeoBits << 1) - res) >> 1
+
+ within := res%document.GeoPrecisionStep == 0 &&
+ geo.RectWithin(minLon, minLat, maxLon, maxLat,
+ sminLon, sminLat, smaxLon, smaxLat)
+ if within || (level == geoDetailLevel &&
+ geo.RectIntersects(minLon, minLat, maxLon, maxLat,
+ sminLon, sminLat, smaxLon, smaxLat)) {
+ if !within && checkBoundaries {
+ return [][]byte{
+ numeric.MustNewPrefixCodedInt64(int64(start), res),
+ }, nil
+ }
+ return nil,
+ [][]byte{
+ numeric.MustNewPrefixCodedInt64(int64(start), res),
+ }
+ } else if level < geoDetailLevel &&
+ geo.RectIntersects(minLon, minLat, maxLon, maxLat,
+ sminLon, sminLat, smaxLon, smaxLat) {
+ return ComputeGeoRange(start, res-1, sminLon, sminLat, smaxLon, smaxLat,
+ checkBoundaries)
+ }
+ return nil, nil
+}
+
+func buildRectFilter(indexReader index.IndexReader, field string,
+ minLon, minLat, maxLon, maxLat float64) FilterFunc {
+ return func(d *search.DocumentMatch) bool {
+ var lon, lat float64
+ var found bool
+ err := indexReader.DocumentVisitFieldTerms(d.IndexInternalID,
+ []string{field}, func(field string, term []byte) {
+ // only consider the values which are shifted 0
+ prefixCoded := numeric.PrefixCoded(term)
+ shift, err := prefixCoded.Shift()
+ if err == nil && shift == 0 {
+ var i64 int64
+ i64, err = prefixCoded.Int64()
+ if err == nil {
+ lon = geo.MortonUnhashLon(uint64(i64))
+ lat = geo.MortonUnhashLat(uint64(i64))
+ found = true
+ }
+ }
+ })
+ if err == nil && found {
+ return geo.BoundingBoxContains(lon, lat,
+ minLon, minLat, maxLon, maxLat)
+ }
+ return false
+ }
+}
diff --git a/vendor/github.com/blevesearch/bleve/search/searcher/search_geopointdistance.go b/vendor/github.com/blevesearch/bleve/search/searcher/search_geopointdistance.go
new file mode 100644
index 0000000000..fd559766fd
--- /dev/null
+++ b/vendor/github.com/blevesearch/bleve/search/searcher/search_geopointdistance.go
@@ -0,0 +1,117 @@
+// Copyright (c) 2017 Couchbase, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package searcher
+
+import (
+ "github.com/blevesearch/bleve/geo"
+ "github.com/blevesearch/bleve/index"
+ "github.com/blevesearch/bleve/numeric"
+ "github.com/blevesearch/bleve/search"
+)
+
+func NewGeoPointDistanceSearcher(indexReader index.IndexReader, centerLon,
+ centerLat, dist float64, field string, boost float64,
+ options search.SearcherOptions) (search.Searcher, error) {
+ // compute bounding box containing the circle
+ topLeftLon, topLeftLat, bottomRightLon, bottomRightLat, err :=
+ geo.RectFromPointDistance(centerLon, centerLat, dist)
+ if err != nil {
+ return nil, err
+ }
+
+ // build a searcher for the box
+ boxSearcher, err := boxSearcher(indexReader,
+ topLeftLon, topLeftLat, bottomRightLon, bottomRightLat,
+ field, boost, options)
+ if err != nil {
+ return nil, err
+ }
+
+ // wrap it in a filtering searcher which checks the actual distance
+ return NewFilteringSearcher(boxSearcher,
+ buildDistFilter(indexReader, field, centerLon, centerLat, dist)), nil
+}
+
+// boxSearcher builds a searcher for the described bounding box
+// if the desired box crosses the dateline, it is automatically split into
+// two boxes joined through a disjunction searcher
+func boxSearcher(indexReader index.IndexReader,
+ topLeftLon, topLeftLat, bottomRightLon, bottomRightLat float64,
+ field string, boost float64, options search.SearcherOptions) (
+ search.Searcher, error) {
+ if bottomRightLon < topLeftLon {
+ // cross date line, rewrite as two parts
+
+ leftSearcher, err := NewGeoBoundingBoxSearcher(indexReader,
+ -180, bottomRightLat, bottomRightLon, topLeftLat,
+ field, boost, options, false)
+ if err != nil {
+ return nil, err
+ }
+ rightSearcher, err := NewGeoBoundingBoxSearcher(indexReader,
+ topLeftLon, bottomRightLat, 180, topLeftLat, field, boost, options, false)
+ if err != nil {
+ _ = leftSearcher.Close()
+ return nil, err
+ }
+
+ boxSearcher, err := NewDisjunctionSearcher(indexReader,
+ []search.Searcher{leftSearcher, rightSearcher}, 0, options)
+ if err != nil {
+ _ = leftSearcher.Close()
+ _ = rightSearcher.Close()
+ return nil, err
+ }
+ return boxSearcher, nil
+ }
+
+ // build geoboundinggox searcher for that bounding box
+ boxSearcher, err := NewGeoBoundingBoxSearcher(indexReader,
+ topLeftLon, bottomRightLat, bottomRightLon, topLeftLat, field, boost,
+ options, false)
+ if err != nil {
+ return nil, err
+ }
+ return boxSearcher, nil
+}
+
+func buildDistFilter(indexReader index.IndexReader, field string,
+ centerLon, centerLat, maxDist float64) FilterFunc {
+ return func(d *search.DocumentMatch) bool {
+ var lon, lat float64
+ var found bool
+ err := indexReader.DocumentVisitFieldTerms(d.IndexInternalID,
+ []string{field}, func(field string, term []byte) {
+ // only consider the values which are shifted 0
+ prefixCoded := numeric.PrefixCoded(term)
+ shift, err := prefixCoded.Shift()
+ if err == nil && shift == 0 {
+ i64, err := prefixCoded.Int64()
+ if err == nil {
+ lon = geo.MortonUnhashLon(uint64(i64))
+ lat = geo.MortonUnhashLat(uint64(i64))
+ found = true
+ }
+ }
+ })
+ if err == nil && found {
+ dist := geo.Haversin(lon, lat, centerLon, centerLat)
+ if dist <= maxDist/1000 {
+ return true
+ }
+ }
+ return false
+ }
+}
diff --git a/vendor/github.com/blevesearch/bleve/search/searcher/search_match_all.go b/vendor/github.com/blevesearch/bleve/search/searcher/search_match_all.go
index d8163161e7..822db2ea00 100644
--- a/vendor/github.com/blevesearch/bleve/search/searcher/search_match_all.go
+++ b/vendor/github.com/blevesearch/bleve/search/searcher/search_match_all.go
@@ -27,7 +27,7 @@ type MatchAllSearcher struct {
count uint64
}
-func NewMatchAllSearcher(indexReader index.IndexReader, boost float64, explain bool) (*MatchAllSearcher, error) {
+func NewMatchAllSearcher(indexReader index.IndexReader, boost float64, options search.SearcherOptions) (*MatchAllSearcher, error) {
reader, err := indexReader.DocIDReaderAll()
if err != nil {
return nil, err
@@ -37,7 +37,7 @@ func NewMatchAllSearcher(indexReader index.IndexReader, boost float64, explain b
_ = reader.Close()
return nil, err
}
- scorer := scorer.NewConstantScorer(1.0, boost, explain)
+ scorer := scorer.NewConstantScorer(1.0, boost, options)
return &MatchAllSearcher{
indexReader: indexReader,
reader: reader,
diff --git a/vendor/github.com/blevesearch/bleve/search/searcher/search_multi_term.go b/vendor/github.com/blevesearch/bleve/search/searcher/search_multi_term.go
new file mode 100644
index 0000000000..b469beadbb
--- /dev/null
+++ b/vendor/github.com/blevesearch/bleve/search/searcher/search_multi_term.go
@@ -0,0 +1,85 @@
+// Copyright (c) 2017 Couchbase, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package searcher
+
+import (
+ "github.com/blevesearch/bleve/index"
+ "github.com/blevesearch/bleve/search"
+)
+
+func NewMultiTermSearcher(indexReader index.IndexReader, terms []string,
+ field string, boost float64, options search.SearcherOptions, limit bool) (
+ search.Searcher, error) {
+ qsearchers := make([]search.Searcher, len(terms))
+ qsearchersClose := func() {
+ for _, searcher := range qsearchers {
+ if searcher != nil {
+ _ = searcher.Close()
+ }
+ }
+ }
+ for i, term := range terms {
+ var err error
+ qsearchers[i], err = NewTermSearcher(indexReader, term, field, boost, options)
+ if err != nil {
+ qsearchersClose()
+ return nil, err
+ }
+ }
+ // build disjunction searcher of these ranges
+ return newMultiTermSearcherBytes(indexReader, qsearchers, field, boost,
+ options, limit)
+}
+
+func NewMultiTermSearcherBytes(indexReader index.IndexReader, terms [][]byte,
+ field string, boost float64, options search.SearcherOptions, limit bool) (
+ search.Searcher, error) {
+ qsearchers := make([]search.Searcher, len(terms))
+ qsearchersClose := func() {
+ for _, searcher := range qsearchers {
+ if searcher != nil {
+ _ = searcher.Close()
+ }
+ }
+ }
+ for i, term := range terms {
+ var err error
+ qsearchers[i], err = NewTermSearcherBytes(indexReader, term, field, boost, options)
+ if err != nil {
+ qsearchersClose()
+ return nil, err
+ }
+ }
+ return newMultiTermSearcherBytes(indexReader, qsearchers, field, boost,
+ options, limit)
+}
+
+func newMultiTermSearcherBytes(indexReader index.IndexReader,
+ searchers []search.Searcher, field string, boost float64,
+ options search.SearcherOptions, limit bool) (
+ search.Searcher, error) {
+
+ // build disjunction searcher of these ranges
+ searcher, err := newDisjunctionSearcher(indexReader, searchers, 0, options,
+ limit)
+ if err != nil {
+ for _, s := range searchers {
+ _ = s.Close()
+ }
+ return nil, err
+ }
+
+ return searcher, nil
+}
diff --git a/vendor/github.com/blevesearch/bleve/search/searcher/search_numeric_range.go b/vendor/github.com/blevesearch/bleve/search/searcher/search_numeric_range.go
index 03fc0dd22a..7f42d72508 100644
--- a/vendor/github.com/blevesearch/bleve/search/searcher/search_numeric_range.go
+++ b/vendor/github.com/blevesearch/bleve/search/searcher/search_numeric_range.go
@@ -17,22 +17,16 @@ package searcher
import (
"bytes"
"math"
+ "sort"
"github.com/blevesearch/bleve/index"
"github.com/blevesearch/bleve/numeric"
"github.com/blevesearch/bleve/search"
)
-type NumericRangeSearcher struct {
- indexReader index.IndexReader
- min *float64
- max *float64
- field string
- explain bool
- searcher *DisjunctionSearcher
-}
-
-func NewNumericRangeSearcher(indexReader index.IndexReader, min *float64, max *float64, inclusiveMin, inclusiveMax *bool, field string, boost float64, explain bool) (*NumericRangeSearcher, error) {
+func NewNumericRangeSearcher(indexReader index.IndexReader,
+ min *float64, max *float64, inclusiveMin, inclusiveMax *bool, field string,
+ boost float64, options search.SearcherOptions) (search.Searcher, error) {
// account for unbounded edges
if min == nil {
negInf := math.Inf(-1)
@@ -62,64 +56,49 @@ func NewNumericRangeSearcher(indexReader index.IndexReader, min *float64, max *f
// FIXME hard-coded precision, should match field declaration
termRanges := splitInt64Range(minInt64, maxInt64, 4)
terms := termRanges.Enumerate()
- if tooManyClauses(len(terms)) {
- return nil, tooManyClausesErr()
- }
- // enumerate all the terms in the range
- qsearchers := make([]search.Searcher, len(terms))
- qsearchersClose := func() {
- for _, searcher := range qsearchers {
- if searcher != nil {
- _ = searcher.Close()
- }
- }
- }
- for i, term := range terms {
- var err error
- qsearchers[i], err = NewTermSearcher(indexReader, string(term), field, boost, explain)
- if err != nil {
- qsearchersClose()
- return nil, err
- }
- }
- // build disjunction searcher of these ranges
- searcher, err := NewDisjunctionSearcher(indexReader, qsearchers, 0, explain)
+ if len(terms) < 1 {
+ // cannot return MatchNoneSearcher because of interaction with
+ // commit f391b991c20f02681bacd197afc6d8aed444e132
+ return NewMultiTermSearcherBytes(indexReader, terms, field, boost, options,
+ true)
+ }
+ var err error
+ terms, err = filterCandidateTerms(indexReader, terms, field)
if err != nil {
- qsearchersClose()
return nil, err
}
- return &NumericRangeSearcher{
- indexReader: indexReader,
- min: min,
- max: max,
- field: field,
- explain: explain,
- searcher: searcher,
- }, nil
-}
-
-func (s *NumericRangeSearcher) Count() uint64 {
- return s.searcher.Count()
-}
+ if tooManyClauses(len(terms)) {
+ return nil, tooManyClausesErr()
+ }
-func (s *NumericRangeSearcher) Weight() float64 {
- return s.searcher.Weight()
+ return NewMultiTermSearcherBytes(indexReader, terms, field, boost, options,
+ true)
}
-func (s *NumericRangeSearcher) SetQueryNorm(qnorm float64) {
- s.searcher.SetQueryNorm(qnorm)
-}
+func filterCandidateTerms(indexReader index.IndexReader,
+ terms [][]byte, field string) (rv [][]byte, err error) {
+ fieldDict, err := indexReader.FieldDictRange(field, terms[0], terms[len(terms)-1])
+ if err != nil {
+ return nil, err
+ }
-func (s *NumericRangeSearcher) Next(ctx *search.SearchContext) (*search.DocumentMatch, error) {
- return s.searcher.Next(ctx)
-}
+ // enumerate the terms and check against list of terms
+ tfd, err := fieldDict.Next()
+ for err == nil && tfd != nil {
+ termBytes := []byte(tfd.Term)
+ i := sort.Search(len(terms), func(i int) bool { return bytes.Compare(terms[i], termBytes) >= 0 })
+ if i < len(terms) && bytes.Compare(terms[i], termBytes) == 0 {
+ rv = append(rv, terms[i])
+ }
+ terms = terms[i:]
+ tfd, err = fieldDict.Next()
+ }
-func (s *NumericRangeSearcher) Advance(ctx *search.SearchContext, ID index.IndexInternalID) (*search.DocumentMatch, error) {
- return s.searcher.Advance(ctx, ID)
-}
+ if cerr := fieldDict.Close(); cerr != nil && err == nil {
+ err = cerr
+ }
-func (s *NumericRangeSearcher) Close() error {
- return s.searcher.Close()
+ return rv, err
}
type termRange struct {
@@ -190,7 +169,8 @@ func splitInt64Range(minBound, maxBound int64, precisionStep uint) termRanges {
lowerWrapped := nextMinBound < minBound
upperWrapped := nextMaxBound > maxBound
- if shift+precisionStep >= 64 || nextMinBound > nextMaxBound || lowerWrapped || upperWrapped {
+ if shift+precisionStep >= 64 || nextMinBound > nextMaxBound ||
+ lowerWrapped || upperWrapped {
// We are in the lowest precision or the next precision is not available.
rv = append(rv, newRange(minBound, maxBound, shift))
// exit the split recursion loop
@@ -225,11 +205,3 @@ func newRangeBytes(minBytes, maxBytes []byte) *termRange {
endTerm: maxBytes,
}
}
-
-func (s *NumericRangeSearcher) Min() int {
- return 0
-}
-
-func (s *NumericRangeSearcher) DocumentMatchPoolSize() int {
- return s.searcher.DocumentMatchPoolSize()
-}
diff --git a/vendor/github.com/blevesearch/bleve/search/searcher/search_phrase.go b/vendor/github.com/blevesearch/bleve/search/searcher/search_phrase.go
index cab87ba75b..e3fa0895d7 100644
--- a/vendor/github.com/blevesearch/bleve/search/searcher/search_phrase.go
+++ b/vendor/github.com/blevesearch/bleve/search/searcher/search_phrase.go
@@ -15,6 +15,7 @@
package searcher
import (
+ "fmt"
"math"
"github.com/blevesearch/bleve/index"
@@ -27,11 +28,72 @@ type PhraseSearcher struct {
queryNorm float64
currMust *search.DocumentMatch
slop int
- terms []string
+ terms [][]string
initialized bool
}
-func NewPhraseSearcher(indexReader index.IndexReader, mustSearcher *ConjunctionSearcher, terms []string) (*PhraseSearcher, error) {
+func NewPhraseSearcher(indexReader index.IndexReader, terms []string, field string, options search.SearcherOptions) (*PhraseSearcher, error) {
+ // turn flat terms []string into [][]string
+ mterms := make([][]string, len(terms))
+ for i, term := range terms {
+ mterms[i] = []string{term}
+ }
+ return NewMultiPhraseSearcher(indexReader, mterms, field, options)
+}
+
+func NewMultiPhraseSearcher(indexReader index.IndexReader, terms [][]string, field string, options search.SearcherOptions) (*PhraseSearcher, error) {
+ options.IncludeTermVectors = true
+ var termPositionSearchers []search.Searcher
+ for _, termPos := range terms {
+ if len(termPos) == 1 && termPos[0] != "" {
+ // single term
+ ts, err := NewTermSearcher(indexReader, termPos[0], field, 1.0, options)
+ if err != nil {
+ // close any searchers already opened
+ for _, ts := range termPositionSearchers {
+ _ = ts.Close()
+ }
+ return nil, fmt.Errorf("phrase searcher error building term searcher: %v", err)
+ }
+ termPositionSearchers = append(termPositionSearchers, ts)
+ } else if len(termPos) > 1 {
+ // multiple terms
+ var termSearchers []search.Searcher
+ for _, term := range termPos {
+ if term == "" {
+ continue
+ }
+ ts, err := NewTermSearcher(indexReader, term, field, 1.0, options)
+ if err != nil {
+ // close any searchers already opened
+ for _, ts := range termPositionSearchers {
+ _ = ts.Close()
+ }
+ return nil, fmt.Errorf("phrase searcher error building term searcher: %v", err)
+ }
+ termSearchers = append(termSearchers, ts)
+ }
+ disjunction, err := NewDisjunctionSearcher(indexReader, termSearchers, 1, options)
+ if err != nil {
+ // close any searchers already opened
+ for _, ts := range termPositionSearchers {
+ _ = ts.Close()
+ }
+ return nil, fmt.Errorf("phrase searcher error building term position disjunction searcher: %v", err)
+ }
+ termPositionSearchers = append(termPositionSearchers, disjunction)
+ }
+ }
+
+ mustSearcher, err := NewConjunctionSearcher(indexReader, termPositionSearchers, options)
+ if err != nil {
+ // close any searchers already opened
+ for _, ts := range termPositionSearchers {
+ _ = ts.Close()
+ }
+ return nil, fmt.Errorf("phrase searcher error building conjunction searcher: %v", err)
+ }
+
// build our searcher
rv := PhraseSearcher{
indexReader: indexReader,
@@ -96,68 +158,150 @@ func (s *PhraseSearcher) Next(ctx *search.SearchContext) (*search.DocumentMatch,
}
}
- var rv *search.DocumentMatch
for s.currMust != nil {
- rvftlm := make(search.FieldTermLocationMap, 0)
- freq := 0
- firstTerm := s.terms[0]
- for field, termLocMap := range s.currMust.Locations {
- rvtlm := make(search.TermLocationMap, 0)
- locations, ok := termLocMap[firstTerm]
- if ok {
- OUTER:
- for _, location := range locations {
- crvtlm := make(search.TermLocationMap, 0)
- INNER:
- for i := 0; i < len(s.terms); i++ {
- nextTerm := s.terms[i]
- if nextTerm != "" {
- // look through all these term locations
- // to try and find the correct offsets
- nextLocations, ok := termLocMap[nextTerm]
- if ok {
- for _, nextLocation := range nextLocations {
- if nextLocation.Pos == location.Pos+float64(i) && nextLocation.SameArrayElement(location) {
- // found a location match for this term
- crvtlm.AddLocation(nextTerm, nextLocation)
- continue INNER
- }
- }
- // if we got here we didn't find a location match for this term
- continue OUTER
- } else {
- continue OUTER
- }
- }
- }
- // if we got here all the terms matched
- freq++
- search.MergeTermLocationMaps(rvtlm, crvtlm)
- rvftlm[field] = rvtlm
- }
- }
- }
-
- if freq > 0 {
- // return match
- rv = s.currMust
- rv.Locations = rvftlm
- err := s.advanceNextMust(ctx)
- if err != nil {
- return nil, err
- }
- return rv, nil
- }
+ // check this match against phrase constraints
+ rv := s.checkCurrMustMatch(ctx)
+ // prepare for next iteration (either loop or subsequent call to Next())
err := s.advanceNextMust(ctx)
if err != nil {
return nil, err
}
+
+ // if match satisfied phrase constraints return it as a hit
+ if rv != nil {
+ return rv, nil
+ }
}
return nil, nil
}
+// checkCurrMustMatch is soley concerned with determining if the DocumentMatch
+// pointed to by s.currMust (which satisifies the pre-condition searcher)
+// also satisfies the phase constraints. if so, it returns a DocumentMatch
+// for this document, otherwise nil
+func (s *PhraseSearcher) checkCurrMustMatch(ctx *search.SearchContext) *search.DocumentMatch {
+ rvftlm := make(search.FieldTermLocationMap, 0)
+ freq := 0
+ // typically we would expect there to only actually be results in
+ // one field, but we allow for this to not be the case
+ // but, we note that phrase constraints can only be satisfied within
+ // a single field, so we can check them each independently
+ for field, tlm := range s.currMust.Locations {
+
+ f, rvtlm := s.checkCurrMustMatchField(ctx, tlm)
+ if f > 0 {
+ freq += f
+ rvftlm[field] = rvtlm
+ }
+ }
+
+ if freq > 0 {
+ // return match
+ rv := s.currMust
+ rv.Locations = rvftlm
+ return rv
+ }
+
+ return nil
+}
+
+// checkCurrMustMatchField is soley concerned with determining if one particular
+// field within the currMust DocumentMatch Locations satisfies the phase
+// constraints (possibly more than once). if so, the number of times it was
+// satisfied, and these locations are returned. otherwise 0 and either
+// a nil or empty TermLocationMap
+func (s *PhraseSearcher) checkCurrMustMatchField(ctx *search.SearchContext, tlm search.TermLocationMap) (int, search.TermLocationMap) {
+ paths := findPhrasePaths(0, nil, s.terms, tlm, nil, 0)
+ rv := make(search.TermLocationMap, len(s.terms))
+ for _, p := range paths {
+ p.MergeInto(rv)
+ }
+ return len(paths), rv
+}
+
+type phrasePart struct {
+ term string
+ loc *search.Location
+}
+
+type phrasePath []*phrasePart
+
+func (p phrasePath) MergeInto(in search.TermLocationMap) {
+ for _, pp := range p {
+ in[pp.term] = append(in[pp.term], pp.loc)
+ }
+}
+
+// findPhrasePaths is a function to identify phase matches from a set of known
+// term locations. the implementation is recursive, so care must be taken
+// with arguments and return values.
+//
+// prev - the previous location, nil on first invocation
+// phraseTerms - slice containing the phrase terms themselves
+// may contain empty string as placeholder (don't care)
+// tlm - the Term Location Map containing all relevant term locations
+// offset - the offset from the previous that this next term must match
+// p - the current path being explored (appended to in recursive calls)
+// this is the primary state being built during the traversal
+//
+// returns slice of paths, or nil if invocation did not find any successul paths
+func findPhrasePaths(prevPos uint64, ap search.ArrayPositions, phraseTerms [][]string, tlm search.TermLocationMap, p phrasePath, remainingSlop int) []phrasePath {
+
+ // no more terms
+ if len(phraseTerms) < 1 {
+ return []phrasePath{p}
+ }
+
+ car := phraseTerms[0]
+ cdr := phraseTerms[1:]
+
+ // empty term is treated as match (continue)
+ if len(car) == 0 || (len(car) == 1 && car[0] == "") {
+ nextPos := prevPos + 1
+ if prevPos == 0 {
+ // if prevPos was 0, don't set it to 1 (as thats not a real abs pos)
+ nextPos = 0 // don't advance nextPos if prevPos was 0
+ }
+ return findPhrasePaths(nextPos, ap, cdr, tlm, p, remainingSlop)
+ }
+
+ var rv []phrasePath
+ // locations for this term
+ for _, carTerm := range car {
+ locations := tlm[carTerm]
+ for _, loc := range locations {
+ if prevPos != 0 && !loc.ArrayPositions.Equals(ap) {
+ // if the array positions are wrong, can't match, try next location
+ continue
+ }
+
+ // compute distance from previous phrase term
+ dist := 0
+ if prevPos != 0 {
+ dist = editDistance(prevPos+1, loc.Pos)
+ }
+
+ // if enough slop reamining, continue recursively
+ if prevPos == 0 || (remainingSlop-dist) >= 0 {
+ // this location works, add it to the path (but not for empty term)
+ px := append(p, &phrasePart{term: carTerm, loc: loc})
+ rv = append(rv, findPhrasePaths(loc.Pos, loc.ArrayPositions, cdr, tlm, px, remainingSlop-dist)...)
+ }
+ }
+ }
+ return rv
+}
+
+func editDistance(p1, p2 uint64) int {
+ dist := int(p1 - p2)
+ if dist < 0 {
+ return -dist
+ }
+ return dist
+}
+
func (s *PhraseSearcher) Advance(ctx *search.SearchContext, ID index.IndexInternalID) (*search.DocumentMatch, error) {
if !s.initialized {
err := s.initSearchers(ctx)
diff --git a/vendor/github.com/blevesearch/bleve/search/searcher/search_regexp.go b/vendor/github.com/blevesearch/bleve/search/searcher/search_regexp.go
index ceded66d01..b7cf520ac1 100644
--- a/vendor/github.com/blevesearch/bleve/search/searcher/search_regexp.go
+++ b/vendor/github.com/blevesearch/bleve/search/searcher/search_regexp.go
@@ -21,7 +21,14 @@ import (
"github.com/blevesearch/bleve/search"
)
-func NewRegexpSearcher(indexReader index.IndexReader, pattern *regexp.Regexp, field string, boost float64, explain bool) (search.Searcher, error) {
+// NewRegexpSearcher creates a searcher which will match documents that
+// contain terms which match the pattern regexp. The match must be EXACT
+// matching the entire term. The provided regexp SHOULD NOT start with ^
+// or end with $ as this can intefere with the implementation. Separately,
+// matches will be checked to ensure they match the entire term.
+func NewRegexpSearcher(indexReader index.IndexReader, pattern *regexp.Regexp,
+ field string, boost float64, options search.SearcherOptions) (
+ search.Searcher, error) {
prefixTerm, complete := pattern.LiteralPrefix()
var candidateTerms []string
@@ -30,39 +37,19 @@ func NewRegexpSearcher(indexReader index.IndexReader, pattern *regexp.Regexp, fi
candidateTerms = []string{prefixTerm}
} else {
var err error
- candidateTerms, err = findRegexpCandidateTerms(indexReader, pattern, field, prefixTerm)
+ candidateTerms, err = findRegexpCandidateTerms(indexReader, pattern, field,
+ prefixTerm)
if err != nil {
return nil, err
}
}
- // enumerate all the terms in the range
- qsearchers := make([]search.Searcher, 0, len(candidateTerms))
- qsearchersClose := func() {
- for _, searcher := range qsearchers {
- _ = searcher.Close()
- }
- }
- for _, cterm := range candidateTerms {
- qsearcher, err := NewTermSearcher(indexReader, cterm, field, boost, explain)
- if err != nil {
- qsearchersClose()
- return nil, err
- }
- qsearchers = append(qsearchers, qsearcher)
- }
-
- // build disjunction searcher of these ranges
- searcher, err := NewDisjunctionSearcher(indexReader, qsearchers, 0, explain)
- if err != nil {
- qsearchersClose()
- return nil, err
- }
-
- return searcher, err
+ return NewMultiTermSearcher(indexReader, candidateTerms, field, boost,
+ options, true)
}
-func findRegexpCandidateTerms(indexReader index.IndexReader, pattern *regexp.Regexp, field, prefixTerm string) (rv []string, err error) {
+func findRegexpCandidateTerms(indexReader index.IndexReader,
+ pattern *regexp.Regexp, field, prefixTerm string) (rv []string, err error) {
rv = make([]string, 0)
var fieldDict index.FieldDict
if len(prefixTerm) > 0 {
@@ -79,7 +66,8 @@ func findRegexpCandidateTerms(indexReader index.IndexReader, pattern *regexp.Reg
// enumerate the terms and check against regexp
tfd, err := fieldDict.Next()
for err == nil && tfd != nil {
- if pattern.MatchString(tfd.Term) {
+ matchPos := pattern.FindStringIndex(tfd.Term)
+ if matchPos != nil && matchPos[0] == 0 && matchPos[1] == len(tfd.Term) {
rv = append(rv, tfd.Term)
if tooManyClauses(len(rv)) {
return rv, tooManyClausesErr()
diff --git a/vendor/github.com/blevesearch/bleve/search/searcher/search_term.go b/vendor/github.com/blevesearch/bleve/search/searcher/search_term.go
index 73b0a1a562..6fae6ae5ae 100644
--- a/vendor/github.com/blevesearch/bleve/search/searcher/search_term.go
+++ b/vendor/github.com/blevesearch/bleve/search/searcher/search_term.go
@@ -22,16 +22,13 @@ import (
type TermSearcher struct {
indexReader index.IndexReader
- term string
- field string
reader index.TermFieldReader
scorer *scorer.TermQueryScorer
tfd index.TermFieldDoc
- explain bool
}
-func NewTermSearcher(indexReader index.IndexReader, term string, field string, boost float64, explain bool) (*TermSearcher, error) {
- reader, err := indexReader.TermFieldReader([]byte(term), field, true, true, true)
+func NewTermSearcher(indexReader index.IndexReader, term string, field string, boost float64, options search.SearcherOptions) (*TermSearcher, error) {
+ reader, err := indexReader.TermFieldReader([]byte(term), field, true, true, options.IncludeTermVectors)
if err != nil {
return nil, err
}
@@ -40,12 +37,27 @@ func NewTermSearcher(indexReader index.IndexReader, term string, field string, b
_ = reader.Close()
return nil, err
}
- scorer := scorer.NewTermQueryScorer(term, field, boost, count, reader.Count(), explain)
+ scorer := scorer.NewTermQueryScorer([]byte(term), field, boost, count, reader.Count(), options)
+ return &TermSearcher{
+ indexReader: indexReader,
+ reader: reader,
+ scorer: scorer,
+ }, nil
+}
+
+func NewTermSearcherBytes(indexReader index.IndexReader, term []byte, field string, boost float64, options search.SearcherOptions) (*TermSearcher, error) {
+ reader, err := indexReader.TermFieldReader(term, field, true, true, options.IncludeTermVectors)
+ if err != nil {
+ return nil, err
+ }
+ count, err := indexReader.DocCount()
+ if err != nil {
+ _ = reader.Close()
+ return nil, err
+ }
+ scorer := scorer.NewTermQueryScorer(term, field, boost, count, reader.Count(), options)
return &TermSearcher{
indexReader: indexReader,
- term: term,
- field: field,
- explain: explain,
reader: reader,
scorer: scorer,
}, nil
diff --git a/vendor/github.com/blevesearch/bleve/search/searcher/search_term_prefix.go b/vendor/github.com/blevesearch/bleve/search/searcher/search_term_prefix.go
index b666d3b72a..05d092249a 100644
--- a/vendor/github.com/blevesearch/bleve/search/searcher/search_term_prefix.go
+++ b/vendor/github.com/blevesearch/bleve/search/searcher/search_term_prefix.go
@@ -19,93 +19,21 @@ import (
"github.com/blevesearch/bleve/search"
)
-type TermPrefixSearcher struct {
- indexReader index.IndexReader
- prefix string
- field string
- explain bool
- searcher *DisjunctionSearcher
-}
-
-func NewTermPrefixSearcher(indexReader index.IndexReader, prefix string, field string, boost float64, explain bool) (*TermPrefixSearcher, error) {
+func NewTermPrefixSearcher(indexReader index.IndexReader, prefix string,
+ field string, boost float64, options search.SearcherOptions) (
+ search.Searcher, error) {
// find the terms with this prefix
fieldDict, err := indexReader.FieldDictPrefix(field, []byte(prefix))
if err != nil {
return nil, err
}
- // enumerate all the terms in the range
- qsearchers := make([]search.Searcher, 0, 25)
- qsearchersClose := func() {
- for _, searcher := range qsearchers {
- _ = searcher.Close()
- }
- }
-
+ var terms []string
tfd, err := fieldDict.Next()
for err == nil && tfd != nil {
- var qsearcher *TermSearcher
- qsearcher, err = NewTermSearcher(indexReader, string(tfd.Term), field, 1.0, explain)
- if err != nil {
- qsearchersClose()
- _ = fieldDict.Close()
- return nil, err
- }
- qsearchers = append(qsearchers, qsearcher)
+ terms = append(terms, tfd.Term)
tfd, err = fieldDict.Next()
}
- err = fieldDict.Close()
- if err != nil {
- qsearchersClose()
- return nil, err
- }
-
- // build disjunction searcher of these ranges
- searcher, err := NewDisjunctionSearcher(indexReader, qsearchers, 0, explain)
- if err != nil {
- qsearchersClose()
- return nil, err
- }
-
- return &TermPrefixSearcher{
- indexReader: indexReader,
- prefix: prefix,
- field: field,
- explain: explain,
- searcher: searcher,
- }, nil
-}
-
-func (s *TermPrefixSearcher) Count() uint64 {
- return s.searcher.Count()
-}
-
-func (s *TermPrefixSearcher) Weight() float64 {
- return s.searcher.Weight()
-}
-
-func (s *TermPrefixSearcher) SetQueryNorm(qnorm float64) {
- s.searcher.SetQueryNorm(qnorm)
-}
-
-func (s *TermPrefixSearcher) Next(ctx *search.SearchContext) (*search.DocumentMatch, error) {
- return s.searcher.Next(ctx)
-
-}
-
-func (s *TermPrefixSearcher) Advance(ctx *search.SearchContext, ID index.IndexInternalID) (*search.DocumentMatch, error) {
- return s.searcher.Advance(ctx, ID)
-}
-
-func (s *TermPrefixSearcher) Close() error {
- return s.searcher.Close()
-}
-
-func (s *TermPrefixSearcher) Min() int {
- return 0
-}
-
-func (s *TermPrefixSearcher) DocumentMatchPoolSize() int {
- return s.searcher.DocumentMatchPoolSize()
+ return NewMultiTermSearcher(indexReader, terms, field, boost, options, true)
}
diff --git a/vendor/github.com/blevesearch/bleve/search/searcher/search_term_range.go b/vendor/github.com/blevesearch/bleve/search/searcher/search_term_range.go
new file mode 100644
index 0000000000..267c681b47
--- /dev/null
+++ b/vendor/github.com/blevesearch/bleve/search/searcher/search_term_range.go
@@ -0,0 +1,79 @@
+// Copyright (c) 2017 Couchbase, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package searcher
+
+import (
+ "github.com/blevesearch/bleve/index"
+ "github.com/blevesearch/bleve/search"
+)
+
+func NewTermRangeSearcher(indexReader index.IndexReader,
+ min, max []byte, inclusiveMin, inclusiveMax *bool, field string,
+ boost float64, options search.SearcherOptions) (search.Searcher, error) {
+
+ if inclusiveMin == nil {
+ defaultInclusiveMin := true
+ inclusiveMin = &defaultInclusiveMin
+ }
+ if inclusiveMax == nil {
+ defaultInclusiveMax := false
+ inclusiveMax = &defaultInclusiveMax
+ }
+
+ if min == nil {
+ min = []byte{}
+ }
+
+ rangeMax := max
+ if rangeMax != nil {
+ // the term dictionary range end has an unfortunate implementation
+ rangeMax = append(rangeMax, 0)
+ }
+
+ // find the terms with this prefix
+ fieldDict, err := indexReader.FieldDictRange(field, min, rangeMax)
+ if err != nil {
+ return nil, err
+ }
+
+ var terms []string
+ tfd, err := fieldDict.Next()
+ for err == nil && tfd != nil {
+ terms = append(terms, tfd.Term)
+ tfd, err = fieldDict.Next()
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ if len(terms) < 1 {
+ return NewMatchNoneSearcher(indexReader)
+ }
+
+ if !*inclusiveMin && min != nil && string(min) == terms[0] {
+ terms = terms[1:]
+ // check again, as we might have removed only entry
+ if len(terms) < 1 {
+ return NewMatchNoneSearcher(indexReader)
+ }
+ }
+
+ // if our term list included the max, it would be the last item
+ if !*inclusiveMax && max != nil && string(max) == terms[len(terms)-1] {
+ terms = terms[:len(terms)-1]
+ }
+
+ return NewMultiTermSearcher(indexReader, terms, field, boost, options, true)
+}
diff --git a/vendor/github.com/blevesearch/bleve/search/sort.go b/vendor/github.com/blevesearch/bleve/search/sort.go
index 51c18e6ec9..28705d369e 100644
--- a/vendor/github.com/blevesearch/bleve/search/sort.go
+++ b/vendor/github.com/blevesearch/bleve/search/sort.go
@@ -17,9 +17,11 @@ package search
import (
"encoding/json"
"fmt"
+ "math"
"sort"
"strings"
+ "github.com/blevesearch/bleve/geo"
"github.com/blevesearch/bleve/numeric"
)
@@ -27,12 +29,15 @@ var HighTerm = strings.Repeat(string([]byte{0xff}), 10)
var LowTerm = string([]byte{0x00})
type SearchSort interface {
+ UpdateVisitor(field string, term []byte)
Value(a *DocumentMatch) string
Descending() bool
RequiresDocID() bool
RequiresScoring() bool
RequiresFields() []string
+
+ Copy() SearchSort
}
func ParseSearchSortObj(input map[string]interface{}) (SearchSort, error) {
@@ -50,6 +55,31 @@ func ParseSearchSortObj(input map[string]interface{}) (SearchSort, error) {
return &SortScore{
Desc: descending,
}, nil
+ case "geo_distance":
+ field, ok := input["field"].(string)
+ if !ok {
+ return nil, fmt.Errorf("search sort mode geo_distance must specify field")
+ }
+ lon, lat, foundLocation := geo.ExtractGeoPoint(input["location"])
+ if !foundLocation {
+ return nil, fmt.Errorf("unable to parse geo_distance location")
+ }
+ rvd := &SortGeoDistance{
+ Field: field,
+ Desc: descending,
+ Lon: lon,
+ Lat: lat,
+ unitMult: 1.0,
+ }
+ if distUnit, ok := input["unit"].(string); ok {
+ var err error
+ rvd.unitMult, err = geo.ParseDistanceUnit(distUnit)
+ if err != nil {
+ return nil, err
+ }
+ rvd.Unit = distUnit
+ }
+ return rvd, nil
case "field":
field, ok := input["field"].(string)
if !ok {
@@ -171,6 +201,20 @@ func (so SortOrder) Value(doc *DocumentMatch) {
}
}
+func (so SortOrder) UpdateVisitor(field string, term []byte) {
+ for _, soi := range so {
+ soi.UpdateVisitor(field, term)
+ }
+}
+
+func (so SortOrder) Copy() SortOrder {
+ rv := make(SortOrder, len(so))
+ for i, soi := range so {
+ rv[i] = soi.Copy()
+ }
+ return rv
+}
+
// Compare will compare two document matches using the specified sort order
// if both are numbers, we avoid converting back to term
func (so SortOrder) Compare(cachedScoring, cachedDesc []bool, i, j *DocumentMatch) int {
@@ -300,13 +344,24 @@ type SortField struct {
Type SortFieldType
Mode SortFieldMode
Missing SortFieldMissing
+ values []string
+}
+
+// UpdateVisitor notifies this sort field that in this document
+// this field has the specified term
+func (s *SortField) UpdateVisitor(field string, term []byte) {
+ if field == s.Field {
+ s.values = append(s.values, string(term))
+ }
}
// Value returns the sort value of the DocumentMatch
+// it also resets the state of this SortField for
+// processing the next document
func (s *SortField) Value(i *DocumentMatch) string {
- iTerms := i.CachedFieldTerms[s.Field]
- iTerms = s.filterTermsByType(iTerms)
+ iTerms := s.filterTermsByType(s.values)
iTerm := s.filterTermsByMode(iTerms)
+ s.values = nil
return iTerm
}
@@ -368,7 +423,7 @@ func (s *SortField) filterTermsByType(terms []string) []string {
for _, term := range terms {
valid, shift := numeric.ValidPrefixCodedTerm(term)
if valid && shift == 0 {
- termsWithShiftZero = append(termsWithShiftZero)
+ termsWithShiftZero = append(termsWithShiftZero, term)
}
}
terms = termsWithShiftZero
@@ -430,11 +485,23 @@ func (s *SortField) MarshalJSON() ([]byte, error) {
return json.Marshal(sfm)
}
+func (s *SortField) Copy() SearchSort {
+ var rv SortField
+ rv = *s
+ return &rv
+}
+
// SortDocID will sort results by the document identifier
type SortDocID struct {
Desc bool
}
+// UpdateVisitor is a no-op for SortDocID as it's value
+// is not dependent on any field terms
+func (s *SortDocID) UpdateVisitor(field string, term []byte) {
+
+}
+
// Value returns the sort value of the DocumentMatch
func (s *SortDocID) Value(i *DocumentMatch) string {
return i.ID
@@ -461,11 +528,23 @@ func (s *SortDocID) MarshalJSON() ([]byte, error) {
return json.Marshal("_id")
}
+func (s *SortDocID) Copy() SearchSort {
+ var rv SortDocID
+ rv = *s
+ return &rv
+}
+
// SortScore will sort results by the document match score
type SortScore struct {
Desc bool
}
+// UpdateVisitor is a no-op for SortScore as it's value
+// is not dependent on any field terms
+func (s *SortScore) UpdateVisitor(field string, term []byte) {
+
+}
+
// Value returns the sort value of the DocumentMatch
func (s *SortScore) Value(i *DocumentMatch) string {
return "_score"
@@ -491,3 +570,142 @@ func (s *SortScore) MarshalJSON() ([]byte, error) {
}
return json.Marshal("_score")
}
+
+func (s *SortScore) Copy() SearchSort {
+ var rv SortScore
+ rv = *s
+ return &rv
+}
+
+var maxDistance = string(numeric.MustNewPrefixCodedInt64(math.MaxInt64, 0))
+
+// NewSortGeoDistance creates SearchSort instance for sorting documents by
+// their distance from the specified point.
+func NewSortGeoDistance(field, unit string, lon, lat float64, desc bool) (
+ *SortGeoDistance, error) {
+
+ rv := &SortGeoDistance{
+ Field: field,
+ Desc: desc,
+ Unit: unit,
+ Lon: lon,
+ Lat: lat,
+ }
+ var err error
+ rv.unitMult, err = geo.ParseDistanceUnit(unit)
+ if err != nil {
+ return nil, err
+ }
+ return rv, nil
+}
+
+// SortGeoDistance will sort results by the distance of an
+// indexed geo point, from the provided location.
+// Field is the name of the field
+// Descending reverse the sort order (default false)
+type SortGeoDistance struct {
+ Field string
+ Desc bool
+ Unit string
+ values []string
+ Lon float64
+ Lat float64
+ unitMult float64
+}
+
+// UpdateVisitor notifies this sort field that in this document
+// this field has the specified term
+func (s *SortGeoDistance) UpdateVisitor(field string, term []byte) {
+ if field == s.Field {
+ s.values = append(s.values, string(term))
+ }
+}
+
+// Value returns the sort value of the DocumentMatch
+// it also resets the state of this SortField for
+// processing the next document
+func (s *SortGeoDistance) Value(i *DocumentMatch) string {
+ iTerms := s.filterTermsByType(s.values)
+ iTerm := s.filterTermsByMode(iTerms)
+ s.values = nil
+
+ if iTerm == "" {
+ return maxDistance
+ }
+
+ i64, err := numeric.PrefixCoded(iTerm).Int64()
+ if err != nil {
+ return maxDistance
+ }
+ docLon := geo.MortonUnhashLon(uint64(i64))
+ docLat := geo.MortonUnhashLat(uint64(i64))
+
+ dist := geo.Haversin(s.Lon, s.Lat, docLon, docLat)
+ // dist is returned in km, so convert to m
+ dist *= 1000
+ if s.unitMult != 0 {
+ dist /= s.unitMult
+ }
+ distInt64 := numeric.Float64ToInt64(dist)
+ return string(numeric.MustNewPrefixCodedInt64(distInt64, 0))
+}
+
+// Descending determines the order of the sort
+func (s *SortGeoDistance) Descending() bool {
+ return s.Desc
+}
+
+func (s *SortGeoDistance) filterTermsByMode(terms []string) string {
+ if len(terms) >= 1 {
+ return terms[0]
+ }
+
+ return ""
+}
+
+// filterTermsByType attempts to make one pass on the terms
+// return only valid prefix coded numbers with shift of 0
+func (s *SortGeoDistance) filterTermsByType(terms []string) []string {
+ var termsWithShiftZero []string
+ for _, term := range terms {
+ valid, shift := numeric.ValidPrefixCodedTerm(term)
+ if valid && shift == 0 {
+ termsWithShiftZero = append(termsWithShiftZero, term)
+ }
+ }
+ return termsWithShiftZero
+}
+
+// RequiresDocID says this SearchSort does not require the DocID be loaded
+func (s *SortGeoDistance) RequiresDocID() bool { return false }
+
+// RequiresScoring says this SearchStore does not require scoring
+func (s *SortGeoDistance) RequiresScoring() bool { return false }
+
+// RequiresFields says this SearchStore requires the specified stored field
+func (s *SortGeoDistance) RequiresFields() []string { return []string{s.Field} }
+
+func (s *SortGeoDistance) MarshalJSON() ([]byte, error) {
+ sfm := map[string]interface{}{
+ "by": "geo_distance",
+ "field": s.Field,
+ "location": map[string]interface{}{
+ "lon": s.Lon,
+ "lat": s.Lat,
+ },
+ }
+ if s.Unit != "" {
+ sfm["unit"] = s.Unit
+ }
+ if s.Desc {
+ sfm["desc"] = true
+ }
+
+ return json.Marshal(sfm)
+}
+
+func (s *SortGeoDistance) Copy() SearchSort {
+ var rv SortGeoDistance
+ rv = *s
+ return &rv
+}