added match query operator
This commit is contained in:
parent
9089de251f
commit
7a695d1189
|
@ -416,6 +416,19 @@ func ExampleNewConjunctionQuery() {
|
||||||
// document id 2
|
// document id 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleNewMatchQueryOperator() {
|
||||||
|
query := NewMatchQueryOperator("great one", MatchQueryOperatorAnd)
|
||||||
|
searchRequest := NewSearchRequest(query)
|
||||||
|
searchResults, err := example_index.Search(searchRequest)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(searchResults.Hits[0].ID)
|
||||||
|
// Output:
|
||||||
|
// document id 2
|
||||||
|
}
|
||||||
|
|
||||||
func ExampleNewDisjunctionQuery() {
|
func ExampleNewDisjunctionQuery() {
|
||||||
disjuncts := make([]Query, 2)
|
disjuncts := make([]Query, 2)
|
||||||
disjuncts[0] = NewMatchQuery("great")
|
disjuncts[0] = NewMatchQuery("great")
|
||||||
|
|
105
query_match.go
105
query_match.go
|
@ -10,6 +10,7 @@
|
||||||
package bleve
|
package bleve
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/blevesearch/bleve/index"
|
"github.com/blevesearch/bleve/index"
|
||||||
|
@ -17,12 +18,58 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type matchQuery struct {
|
type matchQuery struct {
|
||||||
Match string `json:"match"`
|
Match string `json:"match"`
|
||||||
FieldVal string `json:"field,omitempty"`
|
FieldVal string `json:"field,omitempty"`
|
||||||
Analyzer string `json:"analyzer,omitempty"`
|
Analyzer string `json:"analyzer,omitempty"`
|
||||||
BoostVal float64 `json:"boost,omitempty"`
|
BoostVal float64 `json:"boost,omitempty"`
|
||||||
PrefixVal int `json:"prefix_length"`
|
PrefixVal int `json:"prefix_length"`
|
||||||
FuzzinessVal int `json:"fuzziness"`
|
FuzzinessVal int `json:"fuzziness"`
|
||||||
|
OperatorVal MatchQueryOperator `json:"operator,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MatchQueryOperator int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Document must satisfy AT LEAST ONE of term searches.
|
||||||
|
MatchQueryOperatorOr = 0
|
||||||
|
// Document must satisfy ALL of term searches.
|
||||||
|
MatchQueryOperatorAnd = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
func (o MatchQueryOperator) MarshalJSON() ([]byte, error) {
|
||||||
|
switch o {
|
||||||
|
case MatchQueryOperatorOr:
|
||||||
|
return json.Marshal("or")
|
||||||
|
case MatchQueryOperatorAnd:
|
||||||
|
return json.Marshal("and")
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("cannot marshal match operator %d to JSON", o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *MatchQueryOperator) UnmarshalJSON(data []byte) error {
|
||||||
|
var operatorString string
|
||||||
|
err := json.Unmarshal(data, &operatorString)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch operatorString {
|
||||||
|
case "or":
|
||||||
|
*o = MatchQueryOperatorOr
|
||||||
|
return nil
|
||||||
|
case "and":
|
||||||
|
*o = MatchQueryOperatorAnd
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return matchQueryOperatorUnmarshalError(operatorString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type matchQueryOperatorUnmarshalError string
|
||||||
|
|
||||||
|
func (e matchQueryOperatorUnmarshalError) Error() string {
|
||||||
|
return fmt.Sprintf("cannot unmarshal match operator '%s' from JSON", e)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMatchQuery creates a Query for matching text.
|
// NewMatchQuery creates a Query for matching text.
|
||||||
|
@ -33,8 +80,23 @@ type matchQuery struct {
|
||||||
// must satisfy at least one of these term searches.
|
// must satisfy at least one of these term searches.
|
||||||
func NewMatchQuery(match string) *matchQuery {
|
func NewMatchQuery(match string) *matchQuery {
|
||||||
return &matchQuery{
|
return &matchQuery{
|
||||||
Match: match,
|
Match: match,
|
||||||
BoostVal: 1.0,
|
BoostVal: 1.0,
|
||||||
|
OperatorVal: MatchQueryOperatorOr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMatchQuery creates a Query for matching text.
|
||||||
|
// An Analyzer is chosen based on the field.
|
||||||
|
// Input text is analyzed using this analyzer.
|
||||||
|
// Token terms resulting from this analysis are
|
||||||
|
// used to perform term searches. Result documents
|
||||||
|
// must satisfy term searches according to given operator.
|
||||||
|
func NewMatchQueryOperator(match string, operator MatchQueryOperator) *matchQuery {
|
||||||
|
return &matchQuery{
|
||||||
|
Match: match,
|
||||||
|
BoostVal: 1.0,
|
||||||
|
OperatorVal: operator,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,6 +136,15 @@ func (q *matchQuery) SetPrefix(p int) Query {
|
||||||
return q
|
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) Searcher(i index.IndexReader, m *IndexMapping, explain bool) (search.Searcher, error) {
|
func (q *matchQuery) Searcher(i index.IndexReader, m *IndexMapping, explain bool) (search.Searcher, error) {
|
||||||
|
|
||||||
field := q.FieldVal
|
field := q.FieldVal
|
||||||
|
@ -114,10 +185,22 @@ func (q *matchQuery) Searcher(i index.IndexReader, m *IndexMapping, explain bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldQuery := NewDisjunctionQueryMin(tqs, 1).
|
switch q.OperatorVal {
|
||||||
SetBoost(q.BoostVal)
|
case MatchQueryOperatorOr:
|
||||||
|
shouldQuery := NewDisjunctionQueryMin(tqs, 1).
|
||||||
|
SetBoost(q.BoostVal)
|
||||||
|
|
||||||
return shouldQuery.Searcher(i, m, explain)
|
return shouldQuery.Searcher(i, m, explain)
|
||||||
|
|
||||||
|
case MatchQueryOperatorAnd:
|
||||||
|
mustQuery := NewConjunctionQuery(tqs).
|
||||||
|
SetBoost(q.BoostVal)
|
||||||
|
|
||||||
|
return mustQuery.Searcher(i, m, explain)
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unhandled operator %d", q.OperatorVal)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
noneQuery := NewMatchNoneQuery()
|
noneQuery := NewMatchNoneQuery()
|
||||||
return noneQuery.Searcher(i, m, explain)
|
return noneQuery.Searcher(i, m, explain)
|
||||||
|
|
|
@ -34,6 +34,23 @@ func TestParseQuery(t *testing.T) {
|
||||||
input: []byte(`{"match":"beer","field":"desc"}`),
|
input: []byte(`{"match":"beer","field":"desc"}`),
|
||||||
output: NewMatchQuery("beer").SetField("desc"),
|
output: NewMatchQuery("beer").SetField("desc"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
input: []byte(`{"match":"beer","field":"desc","operator":"or"}`),
|
||||||
|
output: NewMatchQuery("beer").SetField("desc"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: []byte(`{"match":"beer","field":"desc","operator":"and"}`),
|
||||||
|
output: NewMatchQueryOperator("beer", MatchQueryOperatorAnd).SetField("desc"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: []byte(`{"match":"beer","field":"desc","operator":"or"}`),
|
||||||
|
output: NewMatchQueryOperator("beer", MatchQueryOperatorOr).SetField("desc"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: []byte(`{"match":"beer","field":"desc","operator":"does not exist"}`),
|
||||||
|
output: nil,
|
||||||
|
err: matchQueryOperatorUnmarshalError("does not exist"),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
input: []byte(`{"match_phrase":"light beer","field":"desc"}`),
|
input: []byte(`{"match_phrase":"light beer","field":"desc"}`),
|
||||||
output: NewMatchPhraseQuery("light beer").SetField("desc"),
|
output: NewMatchPhraseQuery("light beer").SetField("desc"),
|
||||||
|
|
Loading…
Reference in New Issue