From a5d1d7974c8cfb66d2da3d662f2d7ba5d1f30940 Mon Sep 17 00:00:00 2001
From: Marty Schoch
Date: Fri, 10 Feb 2017 16:46:38 -0500
Subject: [PATCH] add query support for multi-phrase
when parsing json, when we encounter the key "terms", we first
try to parse as traditional phrase query, then if that fails,
we also try parsing it as multi-phrase
---
search/query/multi_phrase.go | 80 +++++++++++++++++++++++++++++++++
search/query/query.go | 8 +++-
test/tests/phrase/searches.json | 21 ++++++++-
3 files changed, 107 insertions(+), 2 deletions(-)
create mode 100644 search/query/multi_phrase.go
diff --git a/search/query/multi_phrase.go b/search/query/multi_phrase.go
new file mode 100644
index 000000000..8a7c9b6ad
--- /dev/null
+++ b/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/search/query/query.go b/search/query/query.go
index 1553f621a..0ac12515d 100644
--- a/search/query/query.go
+++ b/search/query/query.go
@@ -123,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
}
diff --git a/test/tests/phrase/searches.json b/test/tests/phrase/searches.json
index 58a4bc0dd..02d23a244 100644
--- a/test/tests/phrase/searches.json
+++ b/test/tests/phrase/searches.json
@@ -372,5 +372,24 @@
"total_hits": 0,
"hits": []
}
+ },
+ {
+ "comment": "multi-phrase terms",
+ "search": {
+ "from": 0,
+ "size": 10,
+ "query": {
+ "field": "body",
+ "terms": [["twenti","thirti"],["thousand"]]
+ }
+ },
+ "result": {
+ "total_hits": 1,
+ "hits": [
+ {
+ "id": "a"
+ }
+ ]
+ }
}
-]
\ No newline at end of file
+]