0
0
Fork 0

heavier refactor of Query interface to simplify

Boostable, Fieldable, Validatable broken out into separate
interfaces.  This allows them to be discoverable when
needed, but ignorable otherwise.  The top-level bleve package
only every cares about Validatable and even that is optional.

Also, this change goes further to make the structure names
more reasonable, for cases where you're directly interacting
with the structures.
This commit is contained in:
Marty Schoch 2016-09-22 19:49:31 -04:00
parent 9ec2ddd757
commit a265218f76
27 changed files with 756 additions and 794 deletions

View File

@ -16,6 +16,7 @@ import (
"net/http"
"github.com/blevesearch/bleve"
"github.com/blevesearch/bleve/search/query"
)
// SearchHandler can handle search requests sent over HTTP
@ -66,10 +67,12 @@ func (h *SearchHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
logger.Printf("parsed request %#v", searchRequest)
// validate the query
err = searchRequest.Query.Validate()
if err != nil {
showError(w, req, fmt.Sprintf("error validating query: %v", err), 400)
return
if srqv, ok := searchRequest.Query.(query.ValidatableQuery); ok {
err = srqv.Validate()
if err != nil {
showError(w, req, fmt.Sprintf("error validating query: %v", err), 400)
return
}
}
// execute the query

View File

@ -351,31 +351,11 @@ type slowQuery struct {
delay time.Duration
}
func (s *slowQuery) Boost() float64 {
return s.actual.Boost()
}
func (s *slowQuery) SetBoost(b float64) query.Query {
return s.actual.SetBoost(b)
}
func (s *slowQuery) Field() string {
return s.actual.Field()
}
func (s *slowQuery) SetField(f string) query.Query {
return s.actual.SetField(f)
}
func (s *slowQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
time.Sleep(s.delay)
return s.actual.Searcher(i, m, explain)
}
func (s *slowQuery) Validate() error {
return s.actual.Validate()
}
func TestSlowSearch(t *testing.T) {
defer func() {
err := os.RemoveAll("testidx")
@ -1132,7 +1112,8 @@ func TestTermVectorArrayPositions(t *testing.T) {
}
// repeat search for this document in Messages field
tq2 := NewTermQuery("third").SetField("Messages")
tq2 := NewTermQuery("third")
tq2.SetField("Messages")
tsr = NewSearchRequest(tq2)
results, err = index.Search(tsr)
if err != nil {
@ -1382,7 +1363,8 @@ func TestDocumentFieldArrayPositionsBug295(t *testing.T) {
}
// search for it in the messages field
tq := NewTermQuery("bleve").SetField("Messages")
tq := NewTermQuery("bleve")
tq.SetField("Messages")
tsr := NewSearchRequest(tq)
results, err := index.Search(tsr)
if err != nil {
@ -1456,7 +1438,9 @@ func TestBooleanFieldMappingIssue109(t *testing.T) {
t.Fatal(err)
}
sreq := NewSearchRequest(NewBoolFieldQuery(true).SetField("Bool"))
q := NewBoolFieldQuery(true)
q.SetField("Bool")
sreq := NewSearchRequest(q)
sres, err := index.Search(sreq)
if err != nil {
t.Fatal(err)
@ -1465,7 +1449,9 @@ func TestBooleanFieldMappingIssue109(t *testing.T) {
t.Errorf("expected 1 results, got %d", sres.Total)
}
sreq = NewSearchRequest(NewBoolFieldQuery(false).SetField("Bool"))
q = NewBoolFieldQuery(false)
q.SetField("Bool")
sreq = NewSearchRequest(q)
sres, err = index.Search(sreq)
if err != nil {
t.Fatal(err)
@ -1719,7 +1705,8 @@ func TestBug408(t *testing.T) {
t.Fatalf("expected %d documents in index, got %d", numToTest, cnt)
}
q := NewTermQuery(matchUserID).SetField("user_id")
q := NewTermQuery(matchUserID)
q.SetField("user_id")
searchReq := NewSearchRequestOptions(q, math.MaxInt32, 0, false)
results, err := index.Search(searchReq)
if err != nil {

View File

@ -207,9 +207,11 @@ type SearchRequest struct {
}
func (sr *SearchRequest) Validate() error {
err := sr.Query.Validate()
if err != nil {
return err
if srq, ok := sr.Query.(query.ValidatableQuery); ok {
err := srq.Validate()
if err != nil {
return err
}
}
return sr.Facets.Validate()

28
search/query/boost.go Normal file
View File

@ -0,0 +1,28 @@
// 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 "fmt"
type Boost float64
func (b *Boost) Value() float64 {
if b == nil {
return 1.0
}
return float64(*b)
}
func (b *Boost) GoString() string {
if b == nil {
return "boost unspecified"
}
return fmt.Sprintf("%f", *b)
}

View File

@ -31,11 +31,27 @@ func SetLog(l *log.Logger) {
// A Query represents a description of the type
// and parameters for a query into the index.
type Query interface {
Boost() float64
SetBoost(b float64) Query
Field() string
SetField(f string) Query
Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error)
}
// A BoostableQuery represents a Query which can be boosted
// relative to other queries.
type BoostableQuery interface {
Query
SetBoost(b float64)
}
// A FieldableQuery represents a Query which can be restricted
// to a single field.
type FieldableQuery interface {
Query
SetField(f string)
}
// A ValidatableQuery represents a Query which can be validated
// prior to execution.
type ValidatableQuery interface {
Query
Validate() error
}
@ -55,9 +71,6 @@ func ParseQuery(input []byte) (Query, error) {
if err != nil {
return nil, err
}
if rv.Boost() == 0 {
rv.SetBoost(1)
}
return &rv, nil
}
_, isTermQuery := tmp["term"]
@ -67,9 +80,6 @@ func ParseQuery(input []byte) (Query, error) {
if err != nil {
return nil, err
}
if rv.Boost() == 0 {
rv.SetBoost(1)
}
return &rv, nil
}
if isMatchQuery {
@ -78,9 +88,6 @@ func ParseQuery(input []byte) (Query, error) {
if err != nil {
return nil, err
}
if rv.Boost() == 0 {
rv.SetBoost(1)
}
return &rv, nil
}
_, isMatchPhraseQuery := tmp["match_phrase"]
@ -90,9 +97,6 @@ func ParseQuery(input []byte) (Query, error) {
if err != nil {
return nil, err
}
if rv.Boost() == 0 {
rv.SetBoost(1)
}
return &rv, nil
}
_, hasMust := tmp["must"]
@ -104,9 +108,6 @@ func ParseQuery(input []byte) (Query, error) {
if err != nil {
return nil, err
}
if rv.Boost() == 0 {
rv.SetBoost(1)
}
return &rv, nil
}
_, hasTerms := tmp["terms"]
@ -116,9 +117,6 @@ func ParseQuery(input []byte) (Query, error) {
if err != nil {
return nil, err
}
if rv.Boost() == 0 {
rv.SetBoost(1)
}
return &rv, nil
}
_, hasConjuncts := tmp["conjuncts"]
@ -128,9 +126,6 @@ func ParseQuery(input []byte) (Query, error) {
if err != nil {
return nil, err
}
if rv.Boost() == 0 {
rv.SetBoost(1)
}
return &rv, nil
}
_, hasDisjuncts := tmp["disjuncts"]
@ -140,9 +135,6 @@ func ParseQuery(input []byte) (Query, error) {
if err != nil {
return nil, err
}
if rv.Boost() == 0 {
rv.SetBoost(1)
}
return &rv, nil
}
@ -153,9 +145,6 @@ func ParseQuery(input []byte) (Query, error) {
if err != nil {
return nil, err
}
if rv.Boost() == 0 {
rv.SetBoost(1)
}
return &rv, nil
}
_, hasMin := tmp["min"]
@ -166,9 +155,6 @@ func ParseQuery(input []byte) (Query, error) {
if err != nil {
return nil, err
}
if rv.Boost() == 0 {
rv.SetBoost(1)
}
return &rv, nil
}
_, hasStart := tmp["start"]
@ -179,9 +165,6 @@ func ParseQuery(input []byte) (Query, error) {
if err != nil {
return nil, err
}
if rv.Boost() == 0 {
rv.SetBoost(1)
}
return &rv, nil
}
_, hasPrefix := tmp["prefix"]
@ -191,9 +174,6 @@ func ParseQuery(input []byte) (Query, error) {
if err != nil {
return nil, err
}
if rv.Boost() == 0 {
rv.SetBoost(1)
}
return &rv, nil
}
_, hasRegexp := tmp["regexp"]
@ -203,9 +183,6 @@ func ParseQuery(input []byte) (Query, error) {
if err != nil {
return nil, err
}
if rv.Boost() == 0 {
rv.SetBoost(1)
}
return &rv, nil
}
_, hasWildcard := tmp["wildcard"]
@ -215,9 +192,6 @@ func ParseQuery(input []byte) (Query, error) {
if err != nil {
return nil, err
}
if rv.Boost() == 0 {
rv.SetBoost(1)
}
return &rv, nil
}
_, hasMatchAll := tmp["match_all"]
@ -227,9 +201,6 @@ func ParseQuery(input []byte) (Query, error) {
if err != nil {
return nil, err
}
if rv.Boost() == 0 {
rv.SetBoost(1)
}
return &rv, nil
}
_, hasMatchNone := tmp["match_none"]
@ -239,9 +210,6 @@ func ParseQuery(input []byte) (Query, error) {
if err != nil {
return nil, err
}
if rv.Boost() == 0 {
rv.SetBoost(1)
}
return &rv, nil
}
_, hasDocIds := tmp["ids"]
@ -251,9 +219,6 @@ func ParseQuery(input []byte) (Query, error) {
if err != nil {
return nil, err
}
if rv.Boost() == 0 {
rv.SetBoost(1)
}
return &rv, nil
}
return nil, fmt.Errorf("unknown query type")

View File

@ -17,49 +17,35 @@ import (
)
type BoolFieldQuery struct {
Bool bool `json:"bool"`
FieldVal string `json:"field,omitempty"`
BoostVal float64 `json:"boost,omitempty"`
Bool bool `json:"bool"`
Field string `json:"field,omitempty"`
Boost *Boost `json:"boost,omitempty"`
}
// NewBoolFieldQuery creates a new Query for boolean fields
func NewBoolFieldQuery(val bool) *BoolFieldQuery {
return &BoolFieldQuery{
Bool: val,
BoostVal: 1.0,
Bool: val,
}
}
func (q *BoolFieldQuery) Boost() float64 {
return q.BoostVal
func (q *BoolFieldQuery) SetBoost(b float64) {
boost := Boost(b)
q.Boost = &boost
}
func (q *BoolFieldQuery) SetBoost(b float64) Query {
q.BoostVal = b
return q
}
func (q *BoolFieldQuery) Field() string {
return q.FieldVal
}
func (q *BoolFieldQuery) SetField(f string) Query {
q.FieldVal = f
return q
func (q *BoolFieldQuery) SetField(f string) {
q.Field = f
}
func (q *BoolFieldQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
field := q.FieldVal
if q.FieldVal == "" {
field := q.Field
if q.Field == "" {
field = m.DefaultSearchField()
}
term := "F"
if q.Bool {
term = "T"
}
return searchers.NewTermSearcher(i, term, field, q.BoostVal, explain)
}
func (q *BoolFieldQuery) Validate() error {
return nil
return searchers.NewTermSearcher(i, term, field, q.Boost.Value(), explain)
}

View File

@ -20,10 +20,10 @@ import (
)
type BooleanQuery struct {
Must Query `json:"must,omitempty"`
Should Query `json:"should,omitempty"`
MustNot Query `json:"must_not,omitempty"`
BoostVal float64 `json:"boost,omitempty"`
Must Query `json:"must,omitempty"`
Should Query `json:"should,omitempty"`
MustNot Query `json:"must_not,omitempty"`
Boost *Boost `json:"boost,omitempty"`
}
// NewBooleanQuery creates a compound Query composed
@ -44,9 +44,7 @@ func NewBooleanQuery(must []Query, should []Query, mustNot []Query) *BooleanQuer
// satisfied.
func NewBooleanQueryMinShould(must []Query, should []Query, mustNot []Query, minShould float64) *BooleanQuery {
rv := BooleanQuery{
BoostVal: 1.0,
}
rv := BooleanQuery{}
if len(must) > 0 {
rv.Must = NewConjunctionQuery(must)
}
@ -93,13 +91,9 @@ func (q *BooleanQuery) AddMustNot(m ...Query) {
}
}
func (q *BooleanQuery) Boost() float64 {
return q.BoostVal
}
func (q *BooleanQuery) SetBoost(b float64) Query {
q.BoostVal = b
return q
func (q *BooleanQuery) SetBoost(b float64) {
boost := Boost(b)
q.Boost = &boost
}
func (q *BooleanQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
@ -139,20 +133,20 @@ func (q *BooleanQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, exp
}
func (q *BooleanQuery) Validate() error {
if q.Must != nil {
err := q.Must.Validate()
if qm, ok := q.Must.(ValidatableQuery); ok {
err := qm.Validate()
if err != nil {
return err
}
}
if q.Should != nil {
err := q.Should.Validate()
if qs, ok := q.Should.(ValidatableQuery); ok {
err := qs.Validate()
if err != nil {
return err
}
}
if q.MustNot != nil {
err := q.MustNot.Validate()
if qmn, ok := q.MustNot.(ValidatableQuery); ok {
err := qmn.Validate()
if err != nil {
return err
}
@ -165,10 +159,10 @@ func (q *BooleanQuery) Validate() error {
func (q *BooleanQuery) UnmarshalJSON(data []byte) error {
tmp := struct {
Must json.RawMessage `json:"must,omitempty"`
Should json.RawMessage `json:"should,omitempty"`
MustNot json.RawMessage `json:"must_not,omitempty"`
BoostVal float64 `json:"boost,omitempty"`
Must json.RawMessage `json:"must,omitempty"`
Should json.RawMessage `json:"should,omitempty"`
MustNot json.RawMessage `json:"must_not,omitempty"`
Boost *Boost `json:"boost,omitempty"`
}{}
err := json.Unmarshal(data, &tmp)
if err != nil {
@ -208,17 +202,7 @@ func (q *BooleanQuery) UnmarshalJSON(data []byte) error {
}
}
q.BoostVal = tmp.BoostVal
if q.BoostVal == 0 {
q.BoostVal = 1
}
q.Boost = tmp.Boost
return nil
}
func (q *BooleanQuery) Field() string {
return ""
}
func (q *BooleanQuery) SetField(f string) Query {
return q
}

View File

@ -20,7 +20,7 @@ import (
type ConjunctionQuery struct {
Conjuncts []Query `json:"conjuncts"`
BoostVal float64 `json:"boost,omitempty"`
Boost *Boost `json:"boost,omitempty"`
}
// NewConjunctionQuery creates a new compound Query.
@ -28,17 +28,12 @@ type ConjunctionQuery struct {
func NewConjunctionQuery(conjuncts []Query) *ConjunctionQuery {
return &ConjunctionQuery{
Conjuncts: conjuncts,
BoostVal: 1.0,
}
}
func (q *ConjunctionQuery) Boost() float64 {
return q.BoostVal
}
func (q *ConjunctionQuery) SetBoost(b float64) Query {
q.BoostVal = b
return q
func (q *ConjunctionQuery) SetBoost(b float64) {
boost := Boost(b)
q.Boost = &boost
}
func (q *ConjunctionQuery) AddQuery(aq Query) *ConjunctionQuery {
@ -60,9 +55,11 @@ func (q *ConjunctionQuery) Searcher(i index.IndexReader, m mapping.IndexMapping,
func (q *ConjunctionQuery) Validate() error {
for _, q := range q.Conjuncts {
err := q.Validate()
if err != nil {
return err
if q, ok := q.(ValidatableQuery); ok {
err := q.Validate()
if err != nil {
return err
}
}
}
return nil
@ -71,7 +68,7 @@ func (q *ConjunctionQuery) Validate() error {
func (q *ConjunctionQuery) UnmarshalJSON(data []byte) error {
tmp := struct {
Conjuncts []json.RawMessage `json:"conjuncts"`
BoostVal float64 `json:"boost,omitempty"`
Boost *Boost `json:"boost,omitempty"`
}{}
err := json.Unmarshal(data, &tmp)
if err != nil {
@ -85,17 +82,6 @@ func (q *ConjunctionQuery) UnmarshalJSON(data []byte) error {
}
q.Conjuncts[i] = query
}
q.BoostVal = tmp.BoostVal
if q.BoostVal == 0 {
q.BoostVal = 1
}
q.Boost = tmp.Boost
return nil
}
func (q *ConjunctionQuery) Field() string {
return ""
}
func (q *ConjunctionQuery) SetField(f string) Query {
return q
}

View File

@ -32,8 +32,8 @@ type DateRangeQuery struct {
End *string `json:"end,omitempty"`
InclusiveStart *bool `json:"inclusive_start,omitempty"`
InclusiveEnd *bool `json:"inclusive_end,omitempty"`
FieldVal string `json:"field,omitempty"`
BoostVal float64 `json:"boost,omitempty"`
Field string `json:"field,omitempty"`
Boost *Boost `json:"boost,omitempty"`
}
// NewDateRangeQuery creates a new Query for ranges
@ -57,26 +57,16 @@ func NewDateRangeInclusiveQuery(start, end *string, startInclusive, endInclusive
End: end,
InclusiveStart: startInclusive,
InclusiveEnd: endInclusive,
BoostVal: 1.0,
}
}
func (q *DateRangeQuery) Boost() float64 {
return q.BoostVal
func (q *DateRangeQuery) SetBoost(b float64) {
boost := Boost(b)
q.Boost = &boost
}
func (q *DateRangeQuery) SetBoost(b float64) Query {
q.BoostVal = b
return q
}
func (q *DateRangeQuery) Field() string {
return q.FieldVal
}
func (q *DateRangeQuery) SetField(f string) Query {
q.FieldVal = f
return q
func (q *DateRangeQuery) SetField(f string) {
q.Field = f
}
func (q *DateRangeQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
@ -86,12 +76,12 @@ func (q *DateRangeQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, e
return nil, err
}
field := q.FieldVal
if q.FieldVal == "" {
field := q.Field
if q.Field == "" {
field = m.DefaultSearchField()
}
return searchers.NewNumericRangeSearcher(i, min, max, q.InclusiveStart, q.InclusiveEnd, field, q.BoostVal, explain)
return searchers.NewNumericRangeSearcher(i, min, max, q.InclusiveStart, q.InclusiveEnd, field, q.Boost.Value(), explain)
}
func (q *DateRangeQuery) parseEndpoints() (*float64, *float64, error) {

View File

@ -21,8 +21,8 @@ import (
type DisjunctionQuery struct {
Disjuncts []Query `json:"disjuncts"`
BoostVal float64 `json:"boost,omitempty"`
MinVal float64 `json:"min"`
Boost *Boost `json:"boost,omitempty"`
Min float64 `json:"min"`
}
// NewDisjunctionQuery creates a new compound Query.
@ -30,7 +30,6 @@ type DisjunctionQuery struct {
func NewDisjunctionQuery(disjuncts []Query) *DisjunctionQuery {
return &DisjunctionQuery{
Disjuncts: disjuncts,
BoostVal: 1.0,
}
}
@ -39,32 +38,21 @@ func NewDisjunctionQuery(disjuncts []Query) *DisjunctionQuery {
func NewDisjunctionQueryMin(disjuncts []Query, min float64) *DisjunctionQuery {
return &DisjunctionQuery{
Disjuncts: disjuncts,
BoostVal: 1.0,
MinVal: min,
Min: min,
}
}
func (q *DisjunctionQuery) Boost() float64 {
return q.BoostVal
func (q *DisjunctionQuery) SetBoost(b float64) {
boost := Boost(b)
q.Boost = &boost
}
func (q *DisjunctionQuery) SetBoost(b float64) Query {
q.BoostVal = b
return q
}
func (q *DisjunctionQuery) AddQuery(aq Query) Query {
func (q *DisjunctionQuery) AddQuery(aq Query) {
q.Disjuncts = append(q.Disjuncts, aq)
return q
}
func (q *DisjunctionQuery) Min() float64 {
return q.MinVal
}
func (q *DisjunctionQuery) SetMin(m float64) Query {
q.MinVal = m
return q
func (q *DisjunctionQuery) SetMin(m float64) {
q.Min = m
}
func (q *DisjunctionQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
@ -76,17 +64,19 @@ func (q *DisjunctionQuery) Searcher(i index.IndexReader, m mapping.IndexMapping,
return nil, err
}
}
return searchers.NewDisjunctionSearcher(i, ss, q.MinVal, explain)
return searchers.NewDisjunctionSearcher(i, ss, q.Min, explain)
}
func (q *DisjunctionQuery) Validate() error {
if int(q.MinVal) > len(q.Disjuncts) {
if int(q.Min) > len(q.Disjuncts) {
return fmt.Errorf("disjunction query has fewer than the minimum number of clauses to satisfy")
}
for _, q := range q.Disjuncts {
err := q.Validate()
if err != nil {
return err
if q, ok := q.(ValidatableQuery); ok {
err := q.Validate()
if err != nil {
return err
}
}
}
return nil
@ -95,8 +85,8 @@ func (q *DisjunctionQuery) Validate() error {
func (q *DisjunctionQuery) UnmarshalJSON(data []byte) error {
tmp := struct {
Disjuncts []json.RawMessage `json:"disjuncts"`
BoostVal float64 `json:"boost,omitempty"`
MinVal float64 `json:"min"`
Boost *Boost `json:"boost,omitempty"`
Min float64 `json:"min"`
}{}
err := json.Unmarshal(data, &tmp)
if err != nil {
@ -110,18 +100,7 @@ func (q *DisjunctionQuery) UnmarshalJSON(data []byte) error {
}
q.Disjuncts[i] = query
}
q.BoostVal = tmp.BoostVal
if q.BoostVal == 0 {
q.BoostVal = 1
}
q.MinVal = tmp.MinVal
q.Boost = tmp.Boost
q.Min = tmp.Min
return nil
}
func (q *DisjunctionQuery) Field() string {
return ""
}
func (q *DisjunctionQuery) SetField(f string) Query {
return q
}

View File

@ -17,8 +17,8 @@ import (
)
type DocIDQuery struct {
IDs []string `json:"ids"`
BoostVal float64 `json:"boost,omitempty"`
IDs []string `json:"ids"`
Boost *Boost `json:"boost,omitempty"`
}
// NewDocIDQuery creates a new Query object returning indexed documents among
@ -26,32 +26,15 @@ type DocIDQuery struct {
// other queries output.
func NewDocIDQuery(ids []string) *DocIDQuery {
return &DocIDQuery{
IDs: ids,
BoostVal: 1.0,
IDs: ids,
}
}
func (q *DocIDQuery) Boost() float64 {
return q.BoostVal
}
func (q *DocIDQuery) SetBoost(b float64) Query {
q.BoostVal = b
return q
}
func (q *DocIDQuery) Field() string {
return ""
}
func (q *DocIDQuery) SetField(f string) Query {
return q
func (q *DocIDQuery) SetBoost(b float64) {
boost := Boost(b)
q.Boost = &boost
}
func (q *DocIDQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
return searchers.NewDocIDSearcher(i, q.IDs, q.BoostVal, explain)
}
func (q *DocIDQuery) Validate() error {
return nil
return searchers.NewDocIDSearcher(i, q.IDs, q.Boost.Value(), explain)
}

View File

@ -17,11 +17,11 @@ import (
)
type FuzzyQuery struct {
Term string `json:"term"`
PrefixVal int `json:"prefix_length"`
FuzzinessVal int `json:"fuzziness"`
FieldVal string `json:"field,omitempty"`
BoostVal float64 `json:"boost,omitempty"`
Term string `json:"term"`
Prefix int `json:"prefix_length"`
Fuzziness int `json:"fuzziness"`
Field string `json:"field,omitempty"`
Boost *Boost `json:"boost,omitempty"`
}
// NewFuzzyQuery creates a new Query which finds
@ -33,57 +33,32 @@ type FuzzyQuery struct {
// distance as the fuzziness metric.
func NewFuzzyQuery(term string) *FuzzyQuery {
return &FuzzyQuery{
Term: term,
PrefixVal: 0,
FuzzinessVal: 2,
BoostVal: 1.0,
Term: term,
Fuzziness: 2,
}
}
func (q *FuzzyQuery) Boost() float64 {
return q.BoostVal
func (q *FuzzyQuery) SetBoost(b float64) {
boost := Boost(b)
q.Boost = &boost
}
func (q *FuzzyQuery) SetBoost(b float64) Query {
q.BoostVal = b
return q
func (q *FuzzyQuery) SetField(f string) {
q.Field = f
}
func (q *FuzzyQuery) Field() string {
return q.FieldVal
func (q *FuzzyQuery) SetFuzziness(f int) {
q.Fuzziness = f
}
func (q *FuzzyQuery) SetField(f string) Query {
q.FieldVal = f
return q
}
func (q *FuzzyQuery) Fuzziness() int {
return q.FuzzinessVal
}
func (q *FuzzyQuery) SetFuzziness(f int) Query {
q.FuzzinessVal = f
return q
}
func (q *FuzzyQuery) Prefix() int {
return q.PrefixVal
}
func (q *FuzzyQuery) SetPrefix(p int) Query {
q.PrefixVal = p
return q
func (q *FuzzyQuery) SetPrefix(p int) {
q.Prefix = p
}
func (q *FuzzyQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
field := q.FieldVal
if q.FieldVal == "" {
field := q.Field
if q.Field == "" {
field = m.DefaultSearchField()
}
return searchers.NewFuzzySearcher(i, q.Term, q.PrefixVal, q.FuzzinessVal, field, q.BoostVal, explain)
}
func (q *FuzzyQuery) Validate() error {
return nil
return searchers.NewFuzzySearcher(i, q.Term, q.Prefix, q.Fuzziness, field, q.Boost.Value(), explain)
}

View File

@ -19,13 +19,13 @@ import (
)
type MatchQuery struct {
Match string `json:"match"`
FieldVal string `json:"field,omitempty"`
Analyzer string `json:"analyzer,omitempty"`
BoostVal float64 `json:"boost,omitempty"`
PrefixVal int `json:"prefix_length"`
FuzzinessVal int `json:"fuzziness"`
OperatorVal MatchQueryOperator `json:"operator,omitempty"`
Match string `json:"match"`
Field string `json:"field,omitempty"`
Analyzer string `json:"analyzer,omitempty"`
Boost *Boost `json:"boost,omitempty"`
Prefix int `json:"prefix_length"`
Fuzziness int `json:"fuzziness"`
Operator MatchQueryOperator `json:"operator,omitempty"`
}
type MatchQueryOperator int
@ -75,9 +75,8 @@ func (o *MatchQueryOperator) UnmarshalJSON(data []byte) error {
// must satisfy at least one of these term searches.
func NewMatchQuery(match string) *MatchQuery {
return &MatchQuery{
Match: match,
BoostVal: 1.0,
OperatorVal: MatchQueryOperatorOr,
Match: match,
Operator: MatchQueryOperatorOr,
}
}
@ -89,61 +88,36 @@ func NewMatchQuery(match string) *MatchQuery {
// must satisfy term searches according to given operator.
func NewMatchQueryOperator(match string, operator MatchQueryOperator) *MatchQuery {
return &MatchQuery{
Match: match,
BoostVal: 1.0,
OperatorVal: operator,
Match: match,
Operator: operator,
}
}
func (q *MatchQuery) Boost() float64 {
return q.BoostVal
func (q *MatchQuery) SetBoost(b float64) {
boost := Boost(b)
q.Boost = &boost
}
func (q *MatchQuery) SetBoost(b float64) Query {
q.BoostVal = b
return q
func (q *MatchQuery) SetField(f string) {
q.Field = f
}
func (q *MatchQuery) Field() string {
return q.FieldVal
func (q *MatchQuery) SetFuzziness(f int) {
q.Fuzziness = f
}
func (q *MatchQuery) SetField(f string) Query {
q.FieldVal = f
return q
func (q *MatchQuery) SetPrefix(p int) {
q.Prefix = p
}
func (q *MatchQuery) Fuzziness() int {
return q.FuzzinessVal
}
func (q *MatchQuery) SetFuzziness(f int) Query {
q.FuzzinessVal = f
return q
}
func (q *MatchQuery) Prefix() int {
return q.PrefixVal
}
func (q *MatchQuery) SetPrefix(p int) Query {
q.PrefixVal = p
return q
}
func (q *MatchQuery) Operator() MatchQueryOperator {
return q.OperatorVal
}
func (q *MatchQuery) SetOperator(operator MatchQueryOperator) Query {
q.OperatorVal = operator
return q
func (q *MatchQuery) SetOperator(operator MatchQueryOperator) {
q.Operator = operator
}
func (q *MatchQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
field := q.FieldVal
if q.FieldVal == "" {
field := q.Field
if q.Field == "" {
field = m.DefaultSearchField()
}
@ -163,44 +137,39 @@ func (q *MatchQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, expla
if len(tokens) > 0 {
tqs := make([]Query, len(tokens))
if q.FuzzinessVal != 0 {
if q.Fuzziness != 0 {
for i, token := range tokens {
query := NewFuzzyQuery(string(token.Term))
query.SetFuzziness(q.FuzzinessVal)
query.SetPrefix(q.PrefixVal)
query.SetFuzziness(q.Fuzziness)
query.SetPrefix(q.Prefix)
query.SetField(field)
query.SetBoost(q.BoostVal)
query.SetBoost(q.Boost.Value())
tqs[i] = query
}
} else {
for i, token := range tokens {
tqs[i] = NewTermQuery(string(token.Term)).
SetField(field).
SetBoost(q.BoostVal)
tq := NewTermQuery(string(token.Term))
tq.SetField(field)
tq.SetBoost(q.Boost.Value())
tqs[i] = tq
}
}
switch q.OperatorVal {
switch q.Operator {
case MatchQueryOperatorOr:
shouldQuery := NewDisjunctionQueryMin(tqs, 1).
SetBoost(q.BoostVal)
shouldQuery := NewDisjunctionQueryMin(tqs, 1)
shouldQuery.SetBoost(q.Boost.Value())
return shouldQuery.Searcher(i, m, explain)
case MatchQueryOperatorAnd:
mustQuery := NewConjunctionQuery(tqs).
SetBoost(q.BoostVal)
mustQuery := NewConjunctionQuery(tqs)
mustQuery.SetBoost(q.Boost.Value())
return mustQuery.Searcher(i, m, explain)
default:
return nil, fmt.Errorf("unhandled operator %d", q.OperatorVal)
return nil, fmt.Errorf("unhandled operator %d", q.Operator)
}
}
noneQuery := NewMatchNoneQuery()
return noneQuery.Searcher(i, m, explain)
}
func (q *MatchQuery) Validate() error {
return nil
}

View File

@ -19,45 +19,27 @@ import (
)
type MatchAllQuery struct {
BoostVal float64 `json:"boost,omitempty"`
Boost *Boost `json:"boost,omitempty"`
}
// NewMatchAllQuery creates a Query which will
// match all documents in the index.
func NewMatchAllQuery() *MatchAllQuery {
return &MatchAllQuery{
BoostVal: 1.0,
}
return &MatchAllQuery{}
}
func (q *MatchAllQuery) Boost() float64 {
return q.BoostVal
}
func (q *MatchAllQuery) SetBoost(b float64) Query {
q.BoostVal = b
return q
func (q *MatchAllQuery) SetBoost(b float64) {
boost := Boost(b)
q.Boost = &boost
}
func (q *MatchAllQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
return searchers.NewMatchAllSearcher(i, q.BoostVal, explain)
}
func (q *MatchAllQuery) Validate() error {
return nil
}
func (q *MatchAllQuery) Field() string {
return ""
}
func (q *MatchAllQuery) SetField(f string) Query {
return q
return searchers.NewMatchAllSearcher(i, q.Boost.Value(), explain)
}
func (q *MatchAllQuery) MarshalJSON() ([]byte, error) {
tmp := map[string]interface{}{
"boost": q.BoostVal,
"boost": q.Boost,
"match_all": map[string]interface{}{},
}
return json.Marshal(tmp)

View File

@ -19,45 +19,27 @@ import (
)
type MatchNoneQuery struct {
BoostVal float64 `json:"boost,omitempty"`
Boost *Boost `json:"boost,omitempty"`
}
// NewMatchNoneQuery creates a Query which will not
// match any documents in the index.
func NewMatchNoneQuery() *MatchNoneQuery {
return &MatchNoneQuery{
BoostVal: 1.0,
}
return &MatchNoneQuery{}
}
func (q *MatchNoneQuery) Boost() float64 {
return q.BoostVal
}
func (q *MatchNoneQuery) SetBoost(b float64) Query {
q.BoostVal = b
return q
func (q *MatchNoneQuery) SetBoost(b float64) {
boost := Boost(b)
q.Boost = &boost
}
func (q *MatchNoneQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
return searchers.NewMatchNoneSearcher(i)
}
func (q *MatchNoneQuery) Validate() error {
return nil
}
func (q *MatchNoneQuery) Field() string {
return ""
}
func (q *MatchNoneQuery) SetField(f string) Query {
return q
}
func (q *MatchNoneQuery) MarshalJSON() ([]byte, error) {
tmp := map[string]interface{}{
"boost": q.BoostVal,
"boost": q.Boost,
"match_none": map[string]interface{}{},
}
return json.Marshal(tmp)

View File

@ -19,10 +19,10 @@ import (
)
type MatchPhraseQuery struct {
MatchPhrase string `json:"match_phrase"`
FieldVal string `json:"field,omitempty"`
Analyzer string `json:"analyzer,omitempty"`
BoostVal float64 `json:"boost,omitempty"`
MatchPhrase string `json:"match_phrase"`
Field string `json:"field,omitempty"`
Analyzer string `json:"analyzer,omitempty"`
Boost *Boost `json:"boost,omitempty"`
}
// NewMatchPhraseQuery creates a new Query object
@ -36,31 +36,21 @@ type MatchPhraseQuery struct {
func NewMatchPhraseQuery(matchPhrase string) *MatchPhraseQuery {
return &MatchPhraseQuery{
MatchPhrase: matchPhrase,
BoostVal: 1.0,
}
}
func (q *MatchPhraseQuery) Boost() float64 {
return q.BoostVal
func (q *MatchPhraseQuery) SetBoost(b float64) {
boost := Boost(b)
q.Boost = &boost
}
func (q *MatchPhraseQuery) SetBoost(b float64) Query {
q.BoostVal = b
return q
}
func (q *MatchPhraseQuery) Field() string {
return q.FieldVal
}
func (q *MatchPhraseQuery) SetField(f string) Query {
q.FieldVal = f
return q
func (q *MatchPhraseQuery) SetField(f string) {
q.Field = f
}
func (q *MatchPhraseQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
field := q.FieldVal
if q.FieldVal == "" {
field := q.Field
if q.Field == "" {
field = m.DefaultSearchField()
}
@ -78,7 +68,8 @@ 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).SetBoost(q.BoostVal)
phraseQuery := NewPhraseQuery(phrase, field)
phraseQuery.SetBoost(q.Boost.Value())
return phraseQuery.Searcher(i, m, explain)
}
noneQuery := NewMatchNoneQuery()
@ -110,7 +101,3 @@ func tokenStreamToPhrase(tokens analysis.TokenStream) []string {
}
return nil
}
func (q *MatchPhraseQuery) Validate() error {
return nil
}

View File

@ -23,8 +23,8 @@ type NumericRangeQuery struct {
Max *float64 `json:"max,omitempty"`
InclusiveMin *bool `json:"inclusive_min,omitempty"`
InclusiveMax *bool `json:"inclusive_max,omitempty"`
FieldVal string `json:"field,omitempty"`
BoostVal float64 `json:"boost,omitempty"`
Field string `json:"field,omitempty"`
Boost *Boost `json:"boost,omitempty"`
}
// NewNumericRangeQuery creates a new Query for ranges
@ -46,34 +46,24 @@ func NewNumericRangeInclusiveQuery(min, max *float64, minInclusive, maxInclusive
Max: max,
InclusiveMin: minInclusive,
InclusiveMax: maxInclusive,
BoostVal: 1.0,
}
}
func (q *NumericRangeQuery) Boost() float64 {
return q.BoostVal
func (q *NumericRangeQuery) SetBoost(b float64) {
boost := Boost(b)
q.Boost = &boost
}
func (q *NumericRangeQuery) SetBoost(b float64) Query {
q.BoostVal = b
return q
}
func (q *NumericRangeQuery) Field() string {
return q.FieldVal
}
func (q *NumericRangeQuery) SetField(f string) Query {
q.FieldVal = f
return q
func (q *NumericRangeQuery) SetField(f string) {
q.Field = f
}
func (q *NumericRangeQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
field := q.FieldVal
if q.FieldVal == "" {
field := q.Field
if q.Field == "" {
field = m.DefaultSearchField()
}
return searchers.NewNumericRangeSearcher(i, q.Min, q.Max, q.InclusiveMin, q.InclusiveMax, field, q.BoostVal, explain)
return searchers.NewNumericRangeSearcher(i, q.Min, q.Max, q.InclusiveMin, q.InclusiveMax, field, q.Boost.Value(), explain)
}
func (q *NumericRangeQuery) Validate() error {

View File

@ -21,8 +21,8 @@ import (
type PhraseQuery struct {
Terms []string `json:"terms"`
FieldVal string `json:"field,omitempty"`
BoostVal float64 `json:"boost,omitempty"`
Field string `json:"field,omitempty"`
Boost *Boost `json:"boost,omitempty"`
termQueries []Query
}
@ -36,24 +36,21 @@ func NewPhraseQuery(terms []string, field string) *PhraseQuery {
termQueries := make([]Query, 0)
for _, term := range terms {
if term != "" {
termQueries = append(termQueries, NewTermQuery(term).SetField(field))
tq := NewTermQuery(term)
tq.SetField(field)
termQueries = append(termQueries, tq)
}
}
return &PhraseQuery{
Terms: terms,
FieldVal: field,
BoostVal: 1.0,
Field: field,
termQueries: termQueries,
}
}
func (q *PhraseQuery) Boost() float64 {
return q.BoostVal
}
func (q *PhraseQuery) SetBoost(b float64) Query {
q.BoostVal = b
return q
func (q *PhraseQuery) SetBoost(b float64) {
boost := Boost(b)
q.Boost = &boost
}
func (q *PhraseQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
@ -81,22 +78,11 @@ func (q *PhraseQuery) UnmarshalJSON(data []byte) error {
return err
}
q.Terms = tmp.Terms
q.FieldVal = tmp.FieldVal
q.BoostVal = tmp.BoostVal
if q.BoostVal == 0 {
q.BoostVal = 1
}
q.Field = tmp.Field
q.Boost = tmp.Boost
q.termQueries = make([]Query, len(q.Terms))
for i, term := range q.Terms {
q.termQueries[i] = &TermQuery{Term: term, FieldVal: q.FieldVal, BoostVal: q.BoostVal}
q.termQueries[i] = &TermQuery{Term: term, Field: q.Field, Boost: q.Boost}
}
return nil
}
func (q *PhraseQuery) Field() string {
return ""
}
func (q *PhraseQuery) SetField(f string) Query {
return q
}

View File

@ -17,9 +17,9 @@ import (
)
type PrefixQuery struct {
Prefix string `json:"prefix"`
FieldVal string `json:"field,omitempty"`
BoostVal float64 `json:"boost,omitempty"`
Prefix string `json:"prefix"`
Field string `json:"field,omitempty"`
Boost *Boost `json:"boost,omitempty"`
}
// NewPrefixQuery creates a new Query which finds
@ -27,37 +27,23 @@ type PrefixQuery struct {
// specified prefix.
func NewPrefixQuery(prefix string) *PrefixQuery {
return &PrefixQuery{
Prefix: prefix,
BoostVal: 1.0,
Prefix: prefix,
}
}
func (q *PrefixQuery) Boost() float64 {
return q.BoostVal
func (q *PrefixQuery) SetBoost(b float64) {
boost := Boost(b)
q.Boost = &boost
}
func (q *PrefixQuery) SetBoost(b float64) Query {
q.BoostVal = b
return q
}
func (q *PrefixQuery) Field() string {
return q.FieldVal
}
func (q *PrefixQuery) SetField(f string) Query {
q.FieldVal = f
return q
func (q *PrefixQuery) SetField(f string) {
q.Field = f
}
func (q *PrefixQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
field := q.FieldVal
if q.FieldVal == "" {
field := q.Field
if q.Field == "" {
field = m.DefaultSearchField()
}
return searchers.NewTermPrefixSearcher(i, q.Prefix, field, q.BoostVal, explain)
}
func (q *PrefixQuery) Validate() error {
return nil
return searchers.NewTermPrefixSearcher(i, q.Prefix, field, q.Boost.Value(), explain)
}

View File

@ -20,9 +20,9 @@ import (
)
type RegexpQuery struct {
Regexp string `json:"regexp"`
FieldVal string `json:"field,omitempty"`
BoostVal float64 `json:"boost,omitempty"`
Regexp string `json:"regexp"`
Field string `json:"field,omitempty"`
Boost *Boost `json:"boost,omitempty"`
compiled *regexp.Regexp
}
@ -31,32 +31,22 @@ type RegexpQuery struct {
// specified regular expression.
func NewRegexpQuery(regexp string) *RegexpQuery {
return &RegexpQuery{
Regexp: regexp,
BoostVal: 1.0,
Regexp: regexp,
}
}
func (q *RegexpQuery) Boost() float64 {
return q.BoostVal
func (q *RegexpQuery) SetBoost(b float64) {
boost := Boost(b)
q.Boost = &boost
}
func (q *RegexpQuery) SetBoost(b float64) Query {
q.BoostVal = b
return q
}
func (q *RegexpQuery) Field() string {
return q.FieldVal
}
func (q *RegexpQuery) SetField(f string) Query {
q.FieldVal = f
return q
func (q *RegexpQuery) SetField(f string) {
q.Field = f
}
func (q *RegexpQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
field := q.FieldVal
if q.FieldVal == "" {
field := q.Field
if q.Field == "" {
field = m.DefaultSearchField()
}
err := q.compile()
@ -64,7 +54,7 @@ func (q *RegexpQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, expl
return nil, err
}
return searchers.NewRegexpSearcher(i, q.compiled, field, q.BoostVal, explain)
return searchers.NewRegexpSearcher(i, q.compiled, field, q.Boost.Value(), explain)
}
func (q *RegexpQuery) Validate() error {

View File

@ -16,8 +16,8 @@ import (
)
type QueryStringQuery struct {
Query string `json:"query"`
BoostVal float64 `json:"boost,omitempty"`
Query string `json:"query"`
Boost *Boost `json:"boost,omitempty"`
}
// NewQueryStringQuery creates a new Query used for
@ -25,18 +25,13 @@ type QueryStringQuery struct {
// query string is a small query language for humans.
func NewQueryStringQuery(query string) *QueryStringQuery {
return &QueryStringQuery{
Query: query,
BoostVal: 1.0,
Query: query,
}
}
func (q *QueryStringQuery) Boost() float64 {
return q.BoostVal
}
func (q *QueryStringQuery) SetBoost(b float64) Query {
q.BoostVal = b
return q
func (q *QueryStringQuery) SetBoost(b float64) {
boost := Boost(b)
q.Boost = &boost
}
func (q *QueryStringQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
@ -52,13 +47,8 @@ func (q *QueryStringQuery) Validate() error {
if err != nil {
return err
}
return newQuery.Validate()
}
func (q *QueryStringQuery) Field() string {
return ""
}
func (q *QueryStringQuery) SetField(f string) Query {
return q
if newQuery, ok := newQuery.(ValidatableQuery); ok {
return newQuery.Validate()
}
return nil
}

View File

@ -17,7 +17,8 @@ func logDebugGrammar(format string, v ...interface{}) {
s string
n int
f float64
q Query}
q Query
pf *float64}
%token tSTRING tPHRASE tPLUS tMINUS tCOLON tBOOST tNUMBER tSTRING tGREATER tLESS
tEQUAL tTILDE
@ -28,7 +29,7 @@ tEQUAL tTILDE
%type <s> tTILDE
%type <s> tBOOST
%type <q> searchBase
%type <f> searchSuffix
%type <pf> searchSuffix
%type <n> searchPrefix
%%
@ -50,7 +51,11 @@ searchPart {
searchPart:
searchPrefix searchBase searchSuffix {
query := $2
query.SetBoost($3)
if $3 != nil {
if query, ok := query.(BoostableQuery); ok {
query.SetBoost(*$3)
}
}
switch($1) {
case queryShould:
yylex.(*lexerWrapper).query.AddShould(query)
@ -81,7 +86,7 @@ searchBase:
tSTRING {
str := $1
logDebugGrammar("STRING - %s", str)
var q Query
var q FieldableQuery
if strings.HasPrefix(str, "/") && strings.HasSuffix(str, "/") {
q = NewRegexpQuery(str[1:len(str)-1])
} else if strings.ContainsAny(str, "*?"){
@ -136,7 +141,7 @@ tSTRING tCOLON tSTRING {
field := $1
str := $3
logDebugGrammar("FIELD - %s STRING - %s", field, str)
var q Query
var q FieldableQuery
if strings.HasPrefix(str, "/") && strings.HasSuffix(str, "/") {
q = NewRegexpQuery(str[1:len(str)-1])
} else if strings.ContainsAny(str, "*?"){
@ -152,7 +157,8 @@ tSTRING tCOLON tNUMBER {
field := $1
str := $3
logDebugGrammar("FIELD - %s STRING - %s", field, str)
q := NewMatchQuery(str).SetField(field)
q := NewMatchQuery(str)
q.SetField(field)
$$ = q
}
|
@ -160,7 +166,8 @@ tSTRING tCOLON tPHRASE {
field := $1
phrase := $3
logDebugGrammar("FIELD - %s PHRASE - %s", field, phrase)
q := NewMatchPhraseQuery(phrase).SetField(field)
q := NewMatchPhraseQuery(phrase)
q.SetField(field)
$$ = q
}
|
@ -169,7 +176,8 @@ tSTRING tCOLON tGREATER tNUMBER {
min, _ := strconv.ParseFloat($4, 64)
minInclusive := false
logDebugGrammar("FIELD - GREATER THAN %f", min)
q := NewNumericRangeInclusiveQuery(&min, nil, &minInclusive, nil).SetField(field)
q := NewNumericRangeInclusiveQuery(&min, nil, &minInclusive, nil)
q.SetField(field)
$$ = q
}
|
@ -178,7 +186,8 @@ tSTRING tCOLON tGREATER tEQUAL tNUMBER {
min, _ := strconv.ParseFloat($5, 64)
minInclusive := true
logDebugGrammar("FIELD - GREATER THAN OR EQUAL %f", min)
q := NewNumericRangeInclusiveQuery(&min, nil, &minInclusive, nil).SetField(field)
q := NewNumericRangeInclusiveQuery(&min, nil, &minInclusive, nil)
q.SetField(field)
$$ = q
}
|
@ -187,7 +196,8 @@ tSTRING tCOLON tLESS tNUMBER {
max, _ := strconv.ParseFloat($4, 64)
maxInclusive := false
logDebugGrammar("FIELD - LESS THAN %f", max)
q := NewNumericRangeInclusiveQuery(nil, &max, nil, &maxInclusive).SetField(field)
q := NewNumericRangeInclusiveQuery(nil, &max, nil, &maxInclusive)
q.SetField(field)
$$ = q
}
|
@ -196,7 +206,8 @@ tSTRING tCOLON tLESS tEQUAL tNUMBER {
max, _ := strconv.ParseFloat($5, 64)
maxInclusive := true
logDebugGrammar("FIELD - LESS THAN OR EQUAL %f", max)
q := NewNumericRangeInclusiveQuery(nil, &max, nil, &maxInclusive).SetField(field)
q := NewNumericRangeInclusiveQuery(nil, &max, nil, &maxInclusive)
q.SetField(field)
$$ = q
}
|
@ -206,7 +217,8 @@ tSTRING tCOLON tGREATER tPHRASE {
phrase := $4
logDebugGrammar("FIELD - GREATER THAN DATE %s", phrase)
q := NewDateRangeInclusiveQuery(&phrase, nil, &minInclusive, nil).SetField(field)
q := NewDateRangeInclusiveQuery(&phrase, nil, &minInclusive, nil)
q.SetField(field)
$$ = q
}
|
@ -216,7 +228,8 @@ tSTRING tCOLON tGREATER tEQUAL tPHRASE {
phrase := $5
logDebugGrammar("FIELD - GREATER THAN OR EQUAL DATE %s", phrase)
q := NewDateRangeInclusiveQuery(&phrase, nil, &minInclusive, nil).SetField(field)
q := NewDateRangeInclusiveQuery(&phrase, nil, &minInclusive, nil)
q.SetField(field)
$$ = q
}
|
@ -226,7 +239,8 @@ tSTRING tCOLON tLESS tPHRASE {
phrase := $4
logDebugGrammar("FIELD - LESS THAN DATE %s", phrase)
q := NewDateRangeInclusiveQuery(nil, &phrase, nil, &maxInclusive).SetField(field)
q := NewDateRangeInclusiveQuery(nil, &phrase, nil, &maxInclusive)
q.SetField(field)
$$ = q
}
|
@ -236,20 +250,23 @@ tSTRING tCOLON tLESS tEQUAL tPHRASE {
phrase := $5
logDebugGrammar("FIELD - LESS THAN OR EQUAL DATE %s", phrase)
q := NewDateRangeInclusiveQuery(nil, &phrase, nil, &maxInclusive).SetField(field)
q := NewDateRangeInclusiveQuery(nil, &phrase, nil, &maxInclusive)
q.SetField(field)
$$ = q
};
searchSuffix:
/* empty */ {
$$ = 1.0
$$ = nil
}
|
tBOOST {
$$ = nil
boost, err := strconv.ParseFloat($1, 64)
if err != nil {
yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("invalid boost value: %v", err))
} else {
$$ = &boost
}
$$ = boost
logDebugGrammar("BOOST %f", boost)
};

View File

@ -22,6 +22,7 @@ type yySymType struct {
n int
f float64
q Query
pf *float64
}
const tSTRING = 57346
@ -472,28 +473,32 @@ yydefault:
case 1:
yyDollar = yyS[yypt-1 : yypt+1]
//line query_string.y:37
//line query_string.y:38
{
logDebugGrammar("INPUT")
}
case 2:
yyDollar = yyS[yypt-2 : yypt+1]
//line query_string.y:42
//line query_string.y:43
{
logDebugGrammar("SEARCH PARTS")
}
case 3:
yyDollar = yyS[yypt-1 : yypt+1]
//line query_string.y:46
//line query_string.y:47
{
logDebugGrammar("SEARCH PART")
}
case 4:
yyDollar = yyS[yypt-3 : yypt+1]
//line query_string.y:51
//line query_string.y:52
{
query := yyDollar[2].q
query.SetBoost(yyDollar[3].f)
if yyDollar[3].pf != nil {
if query, ok := query.(BoostableQuery); ok {
query.SetBoost(*yyDollar[3].pf)
}
}
switch yyDollar[1].n {
case queryShould:
yylex.(*lexerWrapper).query.AddShould(query)
@ -505,31 +510,31 @@ yydefault:
}
case 5:
yyDollar = yyS[yypt-0 : yypt+1]
//line query_string.y:66
//line query_string.y:71
{
yyVAL.n = queryShould
}
case 6:
yyDollar = yyS[yypt-1 : yypt+1]
//line query_string.y:70
//line query_string.y:75
{
logDebugGrammar("PLUS")
yyVAL.n = queryMust
}
case 7:
yyDollar = yyS[yypt-1 : yypt+1]
//line query_string.y:75
//line query_string.y:80
{
logDebugGrammar("MINUS")
yyVAL.n = queryMustNot
}
case 8:
yyDollar = yyS[yypt-1 : yypt+1]
//line query_string.y:81
//line query_string.y:86
{
str := yyDollar[1].s
logDebugGrammar("STRING - %s", str)
var q Query
var q FieldableQuery
if strings.HasPrefix(str, "/") && strings.HasSuffix(str, "/") {
q = NewRegexpQuery(str[1 : len(str)-1])
} else if strings.ContainsAny(str, "*?") {
@ -541,7 +546,7 @@ yydefault:
}
case 9:
yyDollar = yyS[yypt-2 : yypt+1]
//line query_string.y:95
//line query_string.y:100
{
str := yyDollar[1].s
fuzziness, err := strconv.ParseFloat(yyDollar[2].s, 64)
@ -555,7 +560,7 @@ yydefault:
}
case 10:
yyDollar = yyS[yypt-4 : yypt+1]
//line query_string.y:107
//line query_string.y:112
{
field := yyDollar[1].s
str := yyDollar[3].s
@ -571,7 +576,7 @@ yydefault:
}
case 11:
yyDollar = yyS[yypt-1 : yypt+1]
//line query_string.y:121
//line query_string.y:126
{
str := yyDollar[1].s
logDebugGrammar("STRING - %s", str)
@ -580,7 +585,7 @@ yydefault:
}
case 12:
yyDollar = yyS[yypt-1 : yypt+1]
//line query_string.y:128
//line query_string.y:133
{
phrase := yyDollar[1].s
logDebugGrammar("PHRASE - %s", phrase)
@ -589,12 +594,12 @@ yydefault:
}
case 13:
yyDollar = yyS[yypt-3 : yypt+1]
//line query_string.y:135
//line query_string.y:140
{
field := yyDollar[1].s
str := yyDollar[3].s
logDebugGrammar("FIELD - %s STRING - %s", field, str)
var q Query
var q FieldableQuery
if strings.HasPrefix(str, "/") && strings.HasSuffix(str, "/") {
q = NewRegexpQuery(str[1 : len(str)-1])
} else if strings.ContainsAny(str, "*?") {
@ -607,131 +612,143 @@ yydefault:
}
case 14:
yyDollar = yyS[yypt-3 : yypt+1]
//line query_string.y:151
//line query_string.y:156
{
field := yyDollar[1].s
str := yyDollar[3].s
logDebugGrammar("FIELD - %s STRING - %s", field, str)
q := NewMatchQuery(str).SetField(field)
q := NewMatchQuery(str)
q.SetField(field)
yyVAL.q = q
}
case 15:
yyDollar = yyS[yypt-3 : yypt+1]
//line query_string.y:159
//line query_string.y:165
{
field := yyDollar[1].s
phrase := yyDollar[3].s
logDebugGrammar("FIELD - %s PHRASE - %s", field, phrase)
q := NewMatchPhraseQuery(phrase).SetField(field)
q := NewMatchPhraseQuery(phrase)
q.SetField(field)
yyVAL.q = q
}
case 16:
yyDollar = yyS[yypt-4 : yypt+1]
//line query_string.y:167
//line query_string.y:174
{
field := yyDollar[1].s
min, _ := strconv.ParseFloat(yyDollar[4].s, 64)
minInclusive := false
logDebugGrammar("FIELD - GREATER THAN %f", min)
q := NewNumericRangeInclusiveQuery(&min, nil, &minInclusive, nil).SetField(field)
q := NewNumericRangeInclusiveQuery(&min, nil, &minInclusive, nil)
q.SetField(field)
yyVAL.q = q
}
case 17:
yyDollar = yyS[yypt-5 : yypt+1]
//line query_string.y:176
//line query_string.y:184
{
field := yyDollar[1].s
min, _ := strconv.ParseFloat(yyDollar[5].s, 64)
minInclusive := true
logDebugGrammar("FIELD - GREATER THAN OR EQUAL %f", min)
q := NewNumericRangeInclusiveQuery(&min, nil, &minInclusive, nil).SetField(field)
q := NewNumericRangeInclusiveQuery(&min, nil, &minInclusive, nil)
q.SetField(field)
yyVAL.q = q
}
case 18:
yyDollar = yyS[yypt-4 : yypt+1]
//line query_string.y:185
//line query_string.y:194
{
field := yyDollar[1].s
max, _ := strconv.ParseFloat(yyDollar[4].s, 64)
maxInclusive := false
logDebugGrammar("FIELD - LESS THAN %f", max)
q := NewNumericRangeInclusiveQuery(nil, &max, nil, &maxInclusive).SetField(field)
q := NewNumericRangeInclusiveQuery(nil, &max, nil, &maxInclusive)
q.SetField(field)
yyVAL.q = q
}
case 19:
yyDollar = yyS[yypt-5 : yypt+1]
//line query_string.y:194
//line query_string.y:204
{
field := yyDollar[1].s
max, _ := strconv.ParseFloat(yyDollar[5].s, 64)
maxInclusive := true
logDebugGrammar("FIELD - LESS THAN OR EQUAL %f", max)
q := NewNumericRangeInclusiveQuery(nil, &max, nil, &maxInclusive).SetField(field)
q := NewNumericRangeInclusiveQuery(nil, &max, nil, &maxInclusive)
q.SetField(field)
yyVAL.q = q
}
case 20:
yyDollar = yyS[yypt-4 : yypt+1]
//line query_string.y:203
//line query_string.y:214
{
field := yyDollar[1].s
minInclusive := false
phrase := yyDollar[4].s
logDebugGrammar("FIELD - GREATER THAN DATE %s", phrase)
q := NewDateRangeInclusiveQuery(&phrase, nil, &minInclusive, nil).SetField(field)
q := NewDateRangeInclusiveQuery(&phrase, nil, &minInclusive, nil)
q.SetField(field)
yyVAL.q = q
}
case 21:
yyDollar = yyS[yypt-5 : yypt+1]
//line query_string.y:213
//line query_string.y:225
{
field := yyDollar[1].s
minInclusive := true
phrase := yyDollar[5].s
logDebugGrammar("FIELD - GREATER THAN OR EQUAL DATE %s", phrase)
q := NewDateRangeInclusiveQuery(&phrase, nil, &minInclusive, nil).SetField(field)
q := NewDateRangeInclusiveQuery(&phrase, nil, &minInclusive, nil)
q.SetField(field)
yyVAL.q = q
}
case 22:
yyDollar = yyS[yypt-4 : yypt+1]
//line query_string.y:223
//line query_string.y:236
{
field := yyDollar[1].s
maxInclusive := false
phrase := yyDollar[4].s
logDebugGrammar("FIELD - LESS THAN DATE %s", phrase)
q := NewDateRangeInclusiveQuery(nil, &phrase, nil, &maxInclusive).SetField(field)
q := NewDateRangeInclusiveQuery(nil, &phrase, nil, &maxInclusive)
q.SetField(field)
yyVAL.q = q
}
case 23:
yyDollar = yyS[yypt-5 : yypt+1]
//line query_string.y:233
//line query_string.y:247
{
field := yyDollar[1].s
maxInclusive := true
phrase := yyDollar[5].s
logDebugGrammar("FIELD - LESS THAN OR EQUAL DATE %s", phrase)
q := NewDateRangeInclusiveQuery(nil, &phrase, nil, &maxInclusive).SetField(field)
q := NewDateRangeInclusiveQuery(nil, &phrase, nil, &maxInclusive)
q.SetField(field)
yyVAL.q = q
}
case 24:
yyDollar = yyS[yypt-0 : yypt+1]
//line query_string.y:244
//line query_string.y:259
{
yyVAL.f = 1.0
yyVAL.pf = nil
}
case 25:
yyDollar = yyS[yypt-1 : yypt+1]
//line query_string.y:248
//line query_string.y:263
{
yyVAL.pf = nil
boost, err := strconv.ParseFloat(yyDollar[1].s, 64)
if err != nil {
yylex.(*lexerWrapper).lex.Error(fmt.Sprintf("invalid boost value: %v", err))
} else {
yyVAL.pf = &boost
}
yyVAL.f = boost
logDebugGrammar("BOOST %f", boost)
}
}

View File

@ -53,7 +53,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewMatchQuery("test").SetField("field"),
func() Query {
q := NewMatchQuery("test")
q.SetField("field")
return q
}(),
},
nil),
},
@ -64,7 +68,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewMatchQuery("t-est").SetField("field"),
func() Query {
q := NewMatchQuery("t-est")
q.SetField("field")
return q
}(),
},
nil),
},
@ -75,7 +83,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewMatchQuery("t+est").SetField("field"),
func() Query {
q := NewMatchQuery("t+est")
q.SetField("field")
return q
}(),
},
nil),
},
@ -86,7 +98,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewMatchQuery("t>est").SetField("field"),
func() Query {
q := NewMatchQuery("t>est")
q.SetField("field")
return q
}(),
},
nil),
},
@ -97,7 +113,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewMatchQuery("t<est").SetField("field"),
func() Query {
q := NewMatchQuery("t<est")
q.SetField("field")
return q
}(),
},
nil),
},
@ -108,7 +128,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewMatchQuery("t=est").SetField("field"),
func() Query {
q := NewMatchQuery("t=est")
q.SetField("field")
return q
}(),
},
nil),
},
@ -117,7 +141,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
mapping: mapping.NewIndexMapping(),
result: NewBooleanQuery(
[]Query{
NewMatchQuery("test1").SetField("field1"),
func() Query {
q := NewMatchQuery("test1")
q.SetField("field1")
return q
}(),
},
nil,
nil),
@ -129,7 +157,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
nil,
nil,
[]Query{
NewMatchQuery("test2").SetField("field2"),
func() Query {
q := NewMatchQuery("test2")
q.SetField("field2")
return q
}(),
}),
},
{
@ -138,7 +170,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewMatchPhraseQuery("test phrase 2").SetField("field3"),
func() Query {
q := NewMatchPhraseQuery("test phrase 2")
q.SetField("field3")
return q
}(),
},
nil),
},
@ -147,7 +183,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
mapping: mapping.NewIndexMapping(),
result: NewBooleanQuery(
[]Query{
NewMatchPhraseQuery("test phrase 1").SetField("field4"),
func() Query {
q := NewMatchPhraseQuery("test phrase 1")
q.SetField("field4")
return q
}(),
},
nil,
nil),
@ -159,7 +199,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
nil,
nil,
[]Query{
NewMatchPhraseQuery("test phrase 2").SetField("field5"),
func() Query {
q := NewMatchPhraseQuery("test phrase 2")
q.SetField("field5")
return q
}(),
}),
},
{
@ -167,13 +211,25 @@ func TestQuerySyntaxParserValid(t *testing.T) {
mapping: mapping.NewIndexMapping(),
result: NewBooleanQuery(
[]Query{
NewMatchQuery("test3").SetField("field6"),
func() Query {
q := NewMatchQuery("test3")
q.SetField("field6")
return q
}(),
},
[]Query{
NewMatchQuery("test5").SetField("field8"),
func() Query {
q := NewMatchQuery("test5")
q.SetField("field8")
return q
}(),
},
[]Query{
NewMatchQuery("test4").SetField("field7"),
func() Query {
q := NewMatchQuery("test4")
q.SetField("field7")
return q
}(),
}),
},
{
@ -182,7 +238,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewMatchQuery("test").SetBoost(3.0),
func() Query {
q := NewMatchQuery("test")
q.SetBoost(3.0)
return q
}(),
},
nil),
},
@ -192,8 +252,16 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewMatchQuery("test").SetBoost(3.0),
NewMatchQuery("other").SetBoost(6.0),
func() Query {
q := NewMatchQuery("test")
q.SetBoost(3.0)
return q
}(),
func() Query {
q := NewMatchQuery("other")
q.SetBoost(6.0)
return q
}(),
},
nil),
},
@ -213,7 +281,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewMatchQuery("33").SetField("field"),
func() Query {
q := NewMatchQuery("33")
q.SetField("field")
return q
}(),
},
nil),
},
@ -233,7 +305,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewMatchQuery("watex").SetFuzziness(1),
func() Query {
q := NewMatchQuery("watex")
q.SetFuzziness(1)
return q
}(),
},
nil),
},
@ -243,7 +319,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewMatchQuery("watex").SetFuzziness(2),
func() Query {
q := NewMatchQuery("watex")
q.SetFuzziness(2)
return q
}(),
},
nil),
},
@ -253,7 +333,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewMatchQuery("watex").SetFuzziness(1),
func() Query {
q := NewMatchQuery("watex")
q.SetFuzziness(1)
return q
}(),
NewMatchQuery("2"),
},
nil),
@ -264,7 +348,12 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewMatchQuery("watex").SetFuzziness(1).SetField("field"),
func() Query {
q := NewMatchQuery("watex")
q.SetFuzziness(1)
q.SetField("field")
return q
}(),
},
nil),
},
@ -274,7 +363,12 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewMatchQuery("watex").SetFuzziness(2).SetField("field"),
func() Query {
q := NewMatchQuery("watex")
q.SetFuzziness(2)
q.SetField("field")
return q
}(),
},
nil),
},
@ -284,7 +378,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewMatchQuery("555c3bb06f7a127cda000005").SetField("field"),
func() Query {
q := NewMatchQuery("555c3bb06f7a127cda000005")
q.SetField("field")
return q
}(),
},
nil),
},
@ -294,7 +392,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewNumericRangeInclusiveQuery(&fivePointOh, nil, &theFalsehood, nil).SetField("field"),
func() Query {
q := NewNumericRangeInclusiveQuery(&fivePointOh, nil, &theFalsehood, nil)
q.SetField("field")
return q
}(),
},
nil),
},
@ -304,7 +406,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewNumericRangeInclusiveQuery(&fivePointOh, nil, &theTruth, nil).SetField("field"),
func() Query {
q := NewNumericRangeInclusiveQuery(&fivePointOh, nil, &theTruth, nil)
q.SetField("field")
return q
}(),
},
nil),
},
@ -314,7 +420,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewNumericRangeInclusiveQuery(nil, &fivePointOh, nil, &theFalsehood).SetField("field"),
func() Query {
q := NewNumericRangeInclusiveQuery(nil, &fivePointOh, nil, &theFalsehood)
q.SetField("field")
return q
}(),
},
nil),
},
@ -324,7 +434,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewNumericRangeInclusiveQuery(nil, &fivePointOh, nil, &theTruth).SetField("field"),
func() Query {
q := NewNumericRangeInclusiveQuery(nil, &fivePointOh, nil, &theTruth)
q.SetField("field")
return q
}(),
},
nil),
},
@ -334,7 +448,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewDateRangeInclusiveQuery(&theDate, nil, &theFalsehood, nil).SetField("field"),
func() Query {
q := NewDateRangeInclusiveQuery(&theDate, nil, &theFalsehood, nil)
q.SetField("field")
return q
}(),
},
nil),
},
@ -344,7 +462,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewDateRangeInclusiveQuery(&theDate, nil, &theTruth, nil).SetField("field"),
func() Query {
q := NewDateRangeInclusiveQuery(&theDate, nil, &theTruth, nil)
q.SetField("field")
return q
}(),
},
nil),
},
@ -354,7 +476,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewDateRangeInclusiveQuery(nil, &theDate, nil, &theFalsehood).SetField("field"),
func() Query {
q := NewDateRangeInclusiveQuery(nil, &theDate, nil, &theFalsehood)
q.SetField("field")
return q
}(),
},
nil),
},
@ -364,7 +490,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewDateRangeInclusiveQuery(nil, &theDate, nil, &theTruth).SetField("field"),
func() Query {
q := NewDateRangeInclusiveQuery(nil, &theDate, nil, &theTruth)
q.SetField("field")
return q
}(),
},
nil),
},
@ -384,7 +514,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewRegexpQuery("mar.*ty").SetField("name"),
func() Query {
q := NewRegexpQuery("mar.*ty")
q.SetField("name")
return q
}(),
},
nil),
},
@ -404,7 +538,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewWildcardQuery("mart*").SetField("name"),
func() Query {
q := NewWildcardQuery("mart*")
q.SetField("name")
return q
}(),
},
nil),
},
@ -429,7 +567,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewMatchQuery("marty:couchbase").SetField("name"),
func() Query {
q := NewMatchQuery("marty:couchbase")
q.SetField("name")
return q
}(),
},
nil),
},
@ -506,7 +648,11 @@ func TestQuerySyntaxParserValid(t *testing.T) {
result: NewBooleanQuery(
nil,
[]Query{
NewMatchQuery(`term`),
func() Query {
q := NewMatchQuery(`term`)
q.SetBoost(1.0)
return q
}(),
},
nil),
},

View File

@ -17,46 +17,32 @@ import (
)
type TermQuery struct {
Term string `json:"term"`
FieldVal string `json:"field,omitempty"`
BoostVal float64 `json:"boost,omitempty"`
Term string `json:"term"`
Field string `json:"field,omitempty"`
Boost *Boost `json:"boost,omitempty"`
}
// NewTermQuery creates a new Query for finding an
// exact term match in the index.
func NewTermQuery(term string) *TermQuery {
return &TermQuery{
Term: term,
BoostVal: 1.0,
Term: term,
}
}
func (q *TermQuery) Boost() float64 {
return q.BoostVal
func (q *TermQuery) SetBoost(b float64) {
boost := Boost(b)
q.Boost = &boost
}
func (q *TermQuery) SetBoost(b float64) Query {
q.BoostVal = b
return q
}
func (q *TermQuery) Field() string {
return q.FieldVal
}
func (q *TermQuery) SetField(f string) Query {
q.FieldVal = f
return q
func (q *TermQuery) SetField(f string) {
q.Field = f
}
func (q *TermQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
field := q.FieldVal
if q.FieldVal == "" {
field := q.Field
if q.Field == "" {
field = m.DefaultSearchField()
}
return searchers.NewTermSearcher(i, q.Term, field, q.BoostVal, explain)
}
func (q *TermQuery) Validate() error {
return nil
return searchers.NewTermSearcher(i, q.Term, field, q.Boost.Value(), explain)
}

View File

@ -29,24 +29,44 @@ func TestParseQuery(t *testing.T) {
err bool
}{
{
input: []byte(`{"term":"water","field":"desc"}`),
output: NewTermQuery("water").SetField("desc"),
input: []byte(`{"term":"water","field":"desc"}`),
output: func() Query {
q := NewTermQuery("water")
q.SetField("desc")
return q
}(),
},
{
input: []byte(`{"match":"beer","field":"desc"}`),
output: NewMatchQuery("beer").SetField("desc"),
input: []byte(`{"match":"beer","field":"desc"}`),
output: func() Query {
q := NewMatchQuery("beer")
q.SetField("desc")
return q
}(),
},
{
input: []byte(`{"match":"beer","field":"desc","operator":"or"}`),
output: NewMatchQuery("beer").SetField("desc"),
input: []byte(`{"match":"beer","field":"desc","operator":"or"}`),
output: func() Query {
q := NewMatchQuery("beer")
q.SetField("desc")
return q
}(),
},
{
input: []byte(`{"match":"beer","field":"desc","operator":"and"}`),
output: NewMatchQueryOperator("beer", MatchQueryOperatorAnd).SetField("desc"),
input: []byte(`{"match":"beer","field":"desc","operator":"and"}`),
output: func() Query {
q := NewMatchQueryOperator("beer", MatchQueryOperatorAnd)
q.SetField("desc")
return q
}(),
},
{
input: []byte(`{"match":"beer","field":"desc","operator":"or"}`),
output: NewMatchQueryOperator("beer", MatchQueryOperatorOr).SetField("desc"),
input: []byte(`{"match":"beer","field":"desc","operator":"or"}`),
output: func() Query {
q := NewMatchQueryOperator("beer", MatchQueryOperatorOr)
q.SetField("desc")
return q
}(),
},
{
input: []byte(`{"match":"beer","field":"desc","operator":"does not exist"}`),
@ -54,15 +74,31 @@ func TestParseQuery(t *testing.T) {
err: true,
},
{
input: []byte(`{"match_phrase":"light beer","field":"desc"}`),
output: NewMatchPhraseQuery("light beer").SetField("desc"),
input: []byte(`{"match_phrase":"light beer","field":"desc"}`),
output: func() Query {
q := NewMatchPhraseQuery("light beer")
q.SetField("desc")
return q
}(),
},
{
input: []byte(`{"must":{"conjuncts": [{"match":"beer","field":"desc"}]},"should":{"disjuncts": [{"match":"water","field":"desc"}],"min":1.0},"must_not":{"disjuncts": [{"match":"devon","field":"desc"}]}}`),
output: NewBooleanQueryMinShould(
[]Query{NewMatchQuery("beer").SetField("desc")},
[]Query{NewMatchQuery("water").SetField("desc")},
[]Query{NewMatchQuery("devon").SetField("desc")},
[]Query{func() Query {
q := NewMatchQuery("beer")
q.SetField("desc")
return q
}()},
[]Query{func() Query {
q := NewMatchQuery("water")
q.SetField("desc")
return q
}()},
[]Query{func() Query {
q := NewMatchQuery("devon")
q.SetField("desc")
return q
}()},
1.0),
},
{
@ -74,16 +110,28 @@ func TestParseQuery(t *testing.T) {
output: NewQueryStringQuery(`+beer "light beer" -devon`),
},
{
input: []byte(`{"min":5.1,"max":7.1,"field":"desc"}`),
output: NewNumericRangeQuery(&minNum, &maxNum).SetField("desc"),
input: []byte(`{"min":5.1,"max":7.1,"field":"desc"}`),
output: func() Query {
q := NewNumericRangeQuery(&minNum, &maxNum)
q.SetField("desc")
return q
}(),
},
{
input: []byte(`{"start":"` + startDate + `","end":"` + endDate + `","field":"desc"}`),
output: NewDateRangeQuery(&startDate, &endDate).SetField("desc"),
input: []byte(`{"start":"` + startDate + `","end":"` + endDate + `","field":"desc"}`),
output: func() Query {
q := NewDateRangeQuery(&startDate, &endDate)
q.SetField("desc")
return q
}(),
},
{
input: []byte(`{"prefix":"budwei","field":"desc"}`),
output: NewPrefixQuery("budwei").SetField("desc"),
input: []byte(`{"prefix":"budwei","field":"desc"}`),
output: func() Query {
q := NewPrefixQuery("budwei")
q.SetField("desc")
return q
}(),
},
{
input: []byte(`{"match_all":{}}`),
@ -116,71 +164,60 @@ func TestParseQuery(t *testing.T) {
}
}
func TestSetGetField(t *testing.T) {
tests := []struct {
query Query
field string
}{
{
query: NewTermQuery("water").SetField("desc"),
field: "desc",
},
{
query: NewMatchQuery("beer").SetField("desc"),
field: "desc",
},
{
query: NewMatchPhraseQuery("light beer").SetField("desc"),
field: "desc",
},
{
query: NewNumericRangeQuery(&minNum, &maxNum).SetField("desc"),
field: "desc",
},
{
query: NewDateRangeQuery(&startDate, &endDate).SetField("desc"),
field: "desc",
},
{
query: NewPrefixQuery("budwei").SetField("desc"),
field: "desc",
},
}
for _, test := range tests {
query := test.query
if query.Field() != test.field {
t.Errorf("expected field '%s', got '%s'", test.field, query.Field())
}
}
}
func TestQueryValidate(t *testing.T) {
tests := []struct {
query Query
err bool
}{
{
query: NewTermQuery("water").SetField("desc"),
query: func() Query {
q := NewTermQuery("water")
q.SetField("desc")
return q
}(),
},
{
query: NewMatchQuery("beer").SetField("desc"),
query: func() Query {
q := NewMatchQuery("beer")
q.SetField("desc")
return q
}(),
},
{
query: NewMatchPhraseQuery("light beer").SetField("desc"),
query: func() Query {
q := NewMatchPhraseQuery("light beer")
q.SetField("desc")
return q
}(),
},
{
query: NewNumericRangeQuery(&minNum, &maxNum).SetField("desc"),
query: func() Query {
q := NewNumericRangeQuery(&minNum, &maxNum)
q.SetField("desc")
return q
}(),
},
{
query: NewNumericRangeQuery(nil, nil).SetField("desc"),
err: true,
query: func() Query {
q := NewNumericRangeQuery(nil, nil)
q.SetField("desc")
return q
}(),
err: true,
},
{
query: NewDateRangeQuery(&startDate, &endDate).SetField("desc"),
query: func() Query {
q := NewDateRangeQuery(&startDate, &endDate)
q.SetField("desc")
return q
}(),
},
{
query: NewPrefixQuery("budwei").SetField("desc"),
query: func() Query {
q := NewPrefixQuery("budwei")
q.SetField("desc")
return q
}(),
},
{
query: NewQueryStringQuery(`+beer "light beer" -devon`),
@ -193,28 +230,56 @@ func TestQueryValidate(t *testing.T) {
err: true,
},
{
query: NewMatchNoneQuery().SetBoost(25),
query: func() Query {
q := NewMatchNoneQuery()
q.SetBoost(25)
return q
}(),
},
{
query: NewMatchAllQuery().SetBoost(25),
query: func() Query {
q := NewMatchAllQuery()
q.SetBoost(25)
return q
}(),
},
{
query: NewBooleanQuery(
[]Query{NewMatchQuery("beer").SetField("desc")},
[]Query{NewMatchQuery("water").SetField("desc")},
[]Query{NewMatchQuery("devon").SetField("desc")}),
[]Query{func() Query {
q := NewMatchQuery("beer")
q.SetField("desc")
return q
}()},
[]Query{func() Query {
q := NewMatchQuery("water")
q.SetField("desc")
return q
}()},
[]Query{func() Query {
q := NewMatchQuery("devon")
q.SetField("desc")
return q
}()}),
},
{
query: NewBooleanQuery(
nil,
nil,
[]Query{NewMatchQuery("devon").SetField("desc")}),
[]Query{func() Query {
q := NewMatchQuery("devon")
q.SetField("desc")
return q
}()}),
},
{
query: NewBooleanQuery(
[]Query{},
[]Query{},
[]Query{NewMatchQuery("devon").SetField("desc")}),
[]Query{func() Query {
q := NewMatchQuery("devon")
q.SetField("desc")
return q
}()}),
},
{
query: NewBooleanQuery(
@ -232,23 +297,41 @@ func TestQueryValidate(t *testing.T) {
},
{
query: NewBooleanQueryMinShould(
[]Query{NewMatchQuery("beer").SetField("desc")},
[]Query{NewMatchQuery("water").SetField("desc")},
[]Query{NewMatchQuery("devon").SetField("desc")},
[]Query{func() Query {
q := NewMatchQuery("beer")
q.SetField("desc")
return q
}()},
[]Query{func() Query {
q := NewMatchQuery("water")
q.SetField("desc")
return q
}()},
[]Query{func() Query {
q := NewMatchQuery("devon")
q.SetField("desc")
return q
}()},
2.0),
err: true,
},
{
query: NewDocIDQuery(nil).SetBoost(25),
query: func() Query {
q := NewDocIDQuery(nil)
q.SetBoost(25)
return q
}(),
},
}
for _, test := range tests {
actual := test.query.Validate()
if actual != nil && !test.err {
t.Errorf("expected no error: %#v got %#v", test.err, actual)
} else if actual == nil && test.err {
t.Errorf("expected error: %#v got %#v", test.err, actual)
if vq, ok := test.query.(ValidatableQuery); ok {
actual := vq.Validate()
if actual != nil && !test.err {
t.Errorf("expected no error: %#v got %#v", test.err, actual)
} else if actual == nil && test.err {
t.Errorf("expected error: %#v got %#v", test.err, actual)
}
}
}
}
@ -266,38 +349,31 @@ func TestDumpQuery(t *testing.T) {
"conjuncts": [
{
"match": "water",
"boost": 1,
"prefix_length": 0,
"fuzziness": 0
}
],
"boost": 1
]
},
"should": {
"disjuncts": [
{
"match": "beer",
"boost": 1,
"prefix_length": 0,
"fuzziness": 0
}
],
"boost": 1,
"min": 0
},
"must_not": {
"disjuncts": [
{
"match": "light",
"boost": 1,
"prefix_length": 0,
"fuzziness": 0
}
],
"boost": 1,
"min": 0
},
"boost": 1
}
}`)
if wanted != s {
t.Fatalf("query:\n%s\ndiffers from expected:\n%s", s, wanted)

View File

@ -39,9 +39,9 @@ var wildcardRegexpReplacer = strings.NewReplacer(
"?", ".")
type WildcardQuery struct {
Wildcard string `json:"wildcard"`
FieldVal string `json:"field,omitempty"`
BoostVal float64 `json:"boost,omitempty"`
Wildcard string `json:"wildcard"`
Field string `json:"field,omitempty"`
Boost *Boost `json:"boost,omitempty"`
compiled *regexp.Regexp
}
@ -53,31 +53,21 @@ type WildcardQuery struct {
func NewWildcardQuery(wildcard string) *WildcardQuery {
return &WildcardQuery{
Wildcard: wildcard,
BoostVal: 1.0,
}
}
func (q *WildcardQuery) Boost() float64 {
return q.BoostVal
func (q *WildcardQuery) SetBoost(b float64) {
boost := Boost(b)
q.Boost = &boost
}
func (q *WildcardQuery) SetBoost(b float64) Query {
q.BoostVal = b
return q
}
func (q *WildcardQuery) Field() string {
return q.FieldVal
}
func (q *WildcardQuery) SetField(f string) Query {
q.FieldVal = f
return q
func (q *WildcardQuery) SetField(f string) {
q.Field = f
}
func (q *WildcardQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) {
field := q.FieldVal
if q.FieldVal == "" {
field := q.Field
if q.Field == "" {
field = m.DefaultSearchField()
}
if q.compiled == nil {
@ -88,7 +78,7 @@ func (q *WildcardQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, ex
}
}
return searchers.NewRegexpSearcher(i, q.compiled, field, q.BoostVal, explain)
return searchers.NewRegexpSearcher(i, q.compiled, field, q.Boost.Value(), explain)
}
func (q *WildcardQuery) Validate() error {