0
0
Fork 0

added conjunction term search/query/score

This commit is contained in:
Marty Schoch 2014-04-24 10:24:19 -06:00
parent aeebcdd7fe
commit aa53d0b340
9 changed files with 621 additions and 1 deletions

View File

@ -24,8 +24,9 @@ func NewDocument(id string) *Document {
}
}
func (d *Document) AddField(f *Field) {
func (d *Document) AddField(f *Field) *Document {
d.Fields = append(d.Fields, f)
return d
}
func (d *Document) String() string {

41
search/base_test.go Normal file
View File

@ -0,0 +1,41 @@
// 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 search
import (
"github.com/couchbaselabs/bleve/document"
"github.com/couchbaselabs/bleve/index/mock"
)
// sets up some mock data used in many tests in this package
var twoDocIndexDocs = []*document.Document{
// must have 4/4 beer
document.NewDocument("1").
AddField(document.NewTextField("name", []byte("marty"))).
AddField(document.NewTextField("desc", []byte("beer beer beer beer"))),
// must have 1/4 beer
document.NewDocument("2").
AddField(document.NewTextField("name", []byte("steve"))).
AddField(document.NewTextField("desc", []byte("angst beer couch database"))),
// must have 1/4 beer
document.NewDocument("3").
AddField(document.NewTextField("name", []byte("dustin"))).
AddField(document.NewTextField("desc", []byte("apple beer column dank"))),
// must have 65/65 beer
document.NewDocument("4").
AddField(document.NewTextField("name", []byte("ravi"))).
AddField(document.NewTextField("desc", []byte("beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer beer"))),
// must have 0/x beer
document.NewDocument("5").
AddField(document.NewTextField("name", []byte("bobert"))).
AddField(document.NewTextField("desc", []byte("water"))),
}
var twoDocIndex *mock.MockIndex = mock.NewMockIndexWithDocs(twoDocIndexDocs)

View File

@ -0,0 +1,25 @@
// 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 search
type OrderedSearcherList []Searcher
// sort.Interface
func (otrl OrderedSearcherList) Len() int {
return len(otrl)
}
func (otrl OrderedSearcherList) Less(i, j int) bool {
return otrl[i].Count() < otrl[j].Count()
}
func (otrl OrderedSearcherList) Swap(i, j int) {
otrl[i], otrl[j] = otrl[j], otrl[i]
}

155
search/profile.out Normal file
View File

@ -0,0 +1,155 @@
mode: set
github.com/couchbaselabs/bleve/search/explanation.go:22.42,24.16 2 0
github.com/couchbaselabs/bleve/search/explanation.go:27.2,27.19 1 0
github.com/couchbaselabs/bleve/search/explanation.go:24.16,26.3 1 0
github.com/couchbaselabs/bleve/search/scorer_term.go:34.100,46.13 2 1
github.com/couchbaselabs/bleve/search/scorer_term.go:53.2,53.12 1 1
github.com/couchbaselabs/bleve/search/scorer_term.go:46.13,51.3 1 1
github.com/couchbaselabs/bleve/search/scorer_term.go:56.44,59.2 2 1
github.com/couchbaselabs/bleve/search/scorer_term.go:61.55,67.15 3 1
github.com/couchbaselabs/bleve/search/scorer_term.go:67.15,83.3 5 1
github.com/couchbaselabs/bleve/search/scorer_term.go:86.79,91.9 3 1
github.com/couchbaselabs/bleve/search/scorer_term.go:143.2,143.21 1 1
github.com/couchbaselabs/bleve/search/scorer_term.go:147.2,151.15 2 1
github.com/couchbaselabs/bleve/search/scorer_term.go:155.2,155.60 1 1
github.com/couchbaselabs/bleve/search/scorer_term.go:171.2,171.12 1 1
github.com/couchbaselabs/bleve/search/scorer_term.go:91.9,94.38 2 1
github.com/couchbaselabs/bleve/search/scorer_term.go:100.3,102.16 2 1
github.com/couchbaselabs/bleve/search/scorer_term.go:121.3,121.27 1 1
github.com/couchbaselabs/bleve/search/scorer_term.go:135.3,135.39 1 1
github.com/couchbaselabs/bleve/search/scorer_term.go:94.38,96.4 1 1
github.com/couchbaselabs/bleve/search/scorer_term.go:96.5,98.4 1 1
github.com/couchbaselabs/bleve/search/scorer_term.go:102.16,118.4 5 1
github.com/couchbaselabs/bleve/search/scorer_term.go:121.27,123.17 2 1
github.com/couchbaselabs/bleve/search/scorer_term.go:123.17,132.5 4 1
github.com/couchbaselabs/bleve/search/scorer_term.go:135.39,137.17 2 1
github.com/couchbaselabs/bleve/search/scorer_term.go:137.17,139.5 1 1
github.com/couchbaselabs/bleve/search/scorer_term.go:143.21,145.3 1 1
github.com/couchbaselabs/bleve/search/scorer_term.go:151.15,153.3 1 1
github.com/couchbaselabs/bleve/search/scorer_term.go:155.60,157.39 2 1
github.com/couchbaselabs/bleve/search/scorer_term.go:165.3,168.36 4 1
github.com/couchbaselabs/bleve/search/scorer_term.go:157.39,164.4 2 1
github.com/couchbaselabs/bleve/search/query_term.go:22.37,24.2 1 1
github.com/couchbaselabs/bleve/search/query_term.go:26.67,28.2 1 1
github.com/couchbaselabs/bleve/search/query_term.go:30.38,32.2 1 0
github.com/couchbaselabs/bleve/search/query_term_conjunction.go:21.48,23.2 1 0
github.com/couchbaselabs/bleve/search/query_term_conjunction.go:25.78,27.2 1 0
github.com/couchbaselabs/bleve/search/query_term_conjunction.go:29.49,31.2 1 0
github.com/couchbaselabs/bleve/search/scorer_term_conjunction.go:17.78,21.2 1 1
github.com/couchbaselabs/bleve/search/scorer_term_conjunction.go:23.90,30.15 4 1
github.com/couchbaselabs/bleve/search/scorer_term_conjunction.go:34.2,35.40 2 1
github.com/couchbaselabs/bleve/search/scorer_term_conjunction.go:44.2,45.15 2 1
github.com/couchbaselabs/bleve/search/scorer_term_conjunction.go:49.2,49.25 1 1
github.com/couchbaselabs/bleve/search/scorer_term_conjunction.go:55.2,55.12 1 1
github.com/couchbaselabs/bleve/search/scorer_term_conjunction.go:30.15,32.3 1 1
github.com/couchbaselabs/bleve/search/scorer_term_conjunction.go:35.40,37.16 2 1
github.com/couchbaselabs/bleve/search/scorer_term_conjunction.go:40.3,40.32 1 1
github.com/couchbaselabs/bleve/search/scorer_term_conjunction.go:37.16,39.4 1 1
github.com/couchbaselabs/bleve/search/scorer_term_conjunction.go:40.32,42.4 1 0
github.com/couchbaselabs/bleve/search/scorer_term_conjunction.go:45.15,47.3 1 1
github.com/couchbaselabs/bleve/search/scorer_term_conjunction.go:49.25,51.3 1 0
github.com/couchbaselabs/bleve/search/scorer_term_conjunction.go:51.4,51.31 1 1
github.com/couchbaselabs/bleve/search/scorer_term_conjunction.go:51.31,53.3 1 0
github.com/couchbaselabs/bleve/search/sqrt_cache.go:19.13,21.38 2 1
github.com/couchbaselabs/bleve/search/sqrt_cache.go:21.38,23.3 1 1
github.com/couchbaselabs/bleve/search/collector_top_score.go:24.54,29.2 1 1
github.com/couchbaselabs/bleve/search/collector_top_score.go:31.47,33.2 1 0
github.com/couchbaselabs/bleve/search/collector_top_score.go:35.51,37.2 1 0
github.com/couchbaselabs/bleve/search/collector_top_score.go:39.53,41.2 1 0
github.com/couchbaselabs/bleve/search/collector_top_score.go:43.65,46.32 3 1
github.com/couchbaselabs/bleve/search/collector_top_score.go:51.2,52.16 2 1
github.com/couchbaselabs/bleve/search/collector_top_score.go:55.2,55.12 1 1
github.com/couchbaselabs/bleve/search/collector_top_score.go:46.32,49.3 2 1
github.com/couchbaselabs/bleve/search/collector_top_score.go:52.16,54.3 1 0
github.com/couchbaselabs/bleve/search/collector_top_score.go:58.65,63.30 2 1
github.com/couchbaselabs/bleve/search/collector_top_score.go:67.2,67.56 1 1
github.com/couchbaselabs/bleve/search/collector_top_score.go:81.2,82.33 2 1
github.com/couchbaselabs/bleve/search/collector_top_score.go:63.30,65.3 1 1
github.com/couchbaselabs/bleve/search/collector_top_score.go:67.56,69.28 2 1
github.com/couchbaselabs/bleve/search/collector_top_score.go:69.28,73.35 2 1
github.com/couchbaselabs/bleve/search/collector_top_score.go:77.4,77.10 1 1
github.com/couchbaselabs/bleve/search/collector_top_score.go:73.35,76.5 1 1
github.com/couchbaselabs/bleve/search/collector_top_score.go:82.33,85.3 1 1
github.com/couchbaselabs/bleve/search/collector_top_score.go:88.66,91.55 3 1
github.com/couchbaselabs/bleve/search/collector_top_score.go:95.2,95.11 1 1
github.com/couchbaselabs/bleve/search/collector_top_score.go:91.55,94.3 2 1
github.com/couchbaselabs/bleve/search/ordered_searchers_list.go:15.43,17.2 1 1
github.com/couchbaselabs/bleve/search/ordered_searchers_list.go:19.53,21.2 1 1
github.com/couchbaselabs/bleve/search/ordered_searchers_list.go:23.48,25.2 1 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:27.115,30.40 2 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:38.2,48.16 5 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:52.2,52.17 1 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:30.40,32.17 2 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:35.3,35.26 1 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:32.17,34.4 1 0
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:48.16,50.3 1 0
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:55.54,58.43 2 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:62.2,64.43 2 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:58.43,60.3 1 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:64.43,66.3 1 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:69.57,72.43 2 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:79.2,79.22 1 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:86.2,86.12 1 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:72.43,74.17 2 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:74.17,76.4 1 0
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:79.22,80.24 1 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:80.24,82.4 1 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:82.5,84.4 1 0
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:89.52,91.39 2 0
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:94.2,94.11 1 0
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:91.39,93.3 1 0
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:97.63,98.39 1 0
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:98.39,100.3 1 0
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:103.66,107.24 3 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:150.2,150.16 1 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:107.24,108.44 1 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:135.3,139.17 3 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:142.3,142.24 1 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:148.3,148.8 1 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:108.44,109.36 1 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:109.36,112.19 2 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:115.5,115.26 1 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:119.5,119.37 1 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:112.19,114.6 1 0
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:115.26,117.20 2 0
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:119.37,122.20 2 0
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:125.6,125.27 1 0
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:130.6,130.20 1 0
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:122.20,124.7 1 0
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:125.27,127.7 1 0
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:127.8,129.7 1 0
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:139.17,141.4 1 0
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:142.24,144.4 1 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:144.5,146.4 1 0
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:153.78,156.2 2 0
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:158.50,161.39 2 0
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:164.2,164.12 1 0
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:161.39,163.3 1 0
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:167.43,168.39 1 1
github.com/couchbaselabs/bleve/search/search_term_conjunction.go:168.39,170.3 1 1
github.com/couchbaselabs/bleve/search/search_term.go:22.82,24.16 2 1
github.com/couchbaselabs/bleve/search/search_term.go:27.2,33.8 2 1
github.com/couchbaselabs/bleve/search/search_term.go:24.16,26.3 1 0
github.com/couchbaselabs/bleve/search/search_term.go:36.39,38.2 1 1
github.com/couchbaselabs/bleve/search/search_term.go:40.41,42.2 1 1
github.com/couchbaselabs/bleve/search/search_term.go:44.52,46.2 1 1
github.com/couchbaselabs/bleve/search/search_term.go:48.55,50.16 2 1
github.com/couchbaselabs/bleve/search/search_term.go:54.2,54.22 1 1
github.com/couchbaselabs/bleve/search/search_term.go:59.2,61.22 2 1
github.com/couchbaselabs/bleve/search/search_term.go:50.16,52.3 1 0
github.com/couchbaselabs/bleve/search/search_term.go:54.22,56.3 1 1
github.com/couchbaselabs/bleve/search/search_term.go:65.67,67.16 2 1
github.com/couchbaselabs/bleve/search/search_term.go:71.2,71.22 1 1
github.com/couchbaselabs/bleve/search/search_term.go:76.2,79.22 2 1
github.com/couchbaselabs/bleve/search/search_term.go:67.16,69.3 1 0
github.com/couchbaselabs/bleve/search/search_term.go:71.22,73.3 1 1
github.com/couchbaselabs/bleve/search/search_term.go:82.32,84.2 1 1
github.com/couchbaselabs/bleve/search/util.go:11.76,14.38 2 0
github.com/couchbaselabs/bleve/search/util.go:26.2,26.11 1 0
github.com/couchbaselabs/bleve/search/util.go:14.38,16.53 2 0
github.com/couchbaselabs/bleve/search/util.go:16.53,18.18 2 0
github.com/couchbaselabs/bleve/search/util.go:18.18,20.5 1 0
github.com/couchbaselabs/bleve/search/util.go:20.6,22.5 1 0
github.com/couchbaselabs/bleve/search/util.go:29.71,30.39 1 0
github.com/couchbaselabs/bleve/search/util.go:35.2,35.11 1 0
github.com/couchbaselabs/bleve/search/util.go:30.39,34.3 1 0

View File

@ -0,0 +1,31 @@
// 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 search
import (
"github.com/couchbaselabs/bleve/index"
)
type TermConjunctionQuery struct {
Terms []Query `json:"terms"`
BoostVal float64 `json:"boost"`
Explain bool `json:"explain"`
}
func (q *TermConjunctionQuery) Boost() float64 {
return q.BoostVal
}
func (q *TermConjunctionQuery) Searcher(index index.Index) (Searcher, error) {
return NewTermConjunctionSearcher(index, q)
}
func (q *TermConjunctionQuery) Validate() error {
return nil
}

View File

@ -0,0 +1,56 @@
// 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 search
import ()
type TermConjunctionQueryScorer struct {
explain bool
}
func NewTermConjunctionQueryScorer(explain bool) *TermConjunctionQueryScorer {
return &TermConjunctionQueryScorer{
explain: explain,
}
}
func (s *TermConjunctionQueryScorer) Score(constituents []*DocumentMatch) *DocumentMatch {
rv := DocumentMatch{
ID: constituents[0].ID,
}
var sum float64
var childrenExplanations []*Explanation
if s.explain {
childrenExplanations = make([]*Explanation, len(constituents))
}
locations := []FieldTermLocationMap{}
for i, docMatch := range constituents {
sum += docMatch.Score
if s.explain {
childrenExplanations[i] = docMatch.Expl
}
if docMatch.Locations != nil {
locations = append(locations, docMatch.Locations)
}
}
rv.Score = sum
if s.explain {
rv.Expl = &Explanation{Value: sum, Message: "sum of:", Children: childrenExplanations}
}
if len(locations) == 1 {
rv.Locations = locations[0]
} else if len(locations) > 1 {
rv.Locations = mergeLocations(locations)
}
return &rv
}

View File

@ -0,0 +1,171 @@
// 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 search
import (
"math"
"sort"
"github.com/couchbaselabs/bleve/index"
)
type TermConjunctionSearcher struct {
index index.Index
searchers OrderedSearcherList
queryNorm float64
currs []*DocumentMatch
currentId string
scorer *TermConjunctionQueryScorer
}
func NewTermConjunctionSearcher(index index.Index, query *TermConjunctionQuery) (*TermConjunctionSearcher, error) {
// build the downstream searchres
searchers := make(OrderedSearcherList, len(query.Terms))
for i, termQuery := range query.Terms {
searcher, err := termQuery.Searcher(index)
if err != nil {
return nil, err
}
searchers[i] = searcher
}
// sort the searchers
sort.Sort(searchers)
// build our searcher
rv := TermConjunctionSearcher{
index: index,
searchers: searchers,
currs: make([]*DocumentMatch, len(searchers)),
scorer: NewTermConjunctionQueryScorer(query.Explain),
}
rv.computeQueryNorm()
err := rv.initSearchers()
if err != nil {
return nil, err
}
return &rv, nil
}
func (s *TermConjunctionSearcher) computeQueryNorm() {
// first calculate sum of squared weights
sumOfSquaredWeights := 0.0
for _, termSearcher := range s.searchers {
sumOfSquaredWeights += termSearcher.Weight()
}
// now compute query norm from this
s.queryNorm = 1.0 / math.Sqrt(sumOfSquaredWeights)
// finally tell all the downsteam searchers the norm
for _, termSearcher := range s.searchers {
termSearcher.SetQueryNorm(s.queryNorm)
}
}
func (s *TermConjunctionSearcher) initSearchers() error {
var err error
// get all searchers pointing at their first match
for i, termSearcher := range s.searchers {
s.currs[i], err = termSearcher.Next()
if err != nil {
return err
}
}
if len(s.currs) > 0 {
if s.currs[0] != nil {
s.currentId = s.currs[0].ID
} else {
s.currentId = ""
}
}
return nil
}
func (s *TermConjunctionSearcher) Weight() float64 {
var rv float64
for _, searcher := range s.searchers {
rv += searcher.Weight()
}
return rv
}
func (s *TermConjunctionSearcher) SetQueryNorm(qnorm float64) {
for _, searcher := range s.searchers {
searcher.SetQueryNorm(qnorm)
}
}
func (s *TermConjunctionSearcher) Next() (*DocumentMatch, error) {
var rv *DocumentMatch
var err error
OUTER:
for s.currentId != "" {
for i, termSearcher := range s.searchers {
if s.currs[i].ID != s.currentId {
// this reader doesn't have the currentId, try to advance
s.currs[i], err = termSearcher.Advance(s.currentId)
if err != nil {
return nil, err
}
if s.currs[i] == nil {
s.currentId = ""
continue OUTER
}
if s.currs[i].ID != s.currentId {
// if it still doesn't have the currentId, next and start over
s.currs[i], err = termSearcher.Next()
if err != nil {
return nil, err
}
if s.currs[i] == nil {
s.currentId = ""
} else {
s.currentId = s.currs[i].ID
}
continue OUTER
}
}
}
// if we get here, a doc matched all readers, sum the score and add it
rv = s.scorer.Score(s.currs)
// prepare for next entry
s.currs[0], err = s.searchers[0].Next()
if err != nil {
return nil, err
}
if s.currs[0] == nil {
s.currentId = ""
} else {
s.currentId = s.currs[0].ID
}
// don't continue now, wait for next call the Next()
break
}
return rv, nil
}
func (s *TermConjunctionSearcher) Advance(ID string) (*DocumentMatch, error) {
s.currentId = ID
return s.Next()
}
func (s *TermConjunctionSearcher) Count() uint64 {
// for now return a worst case
var sum uint64 = 0
for _, searcher := range s.searchers {
sum += searcher.Count()
}
return sum
}
func (s *TermConjunctionSearcher) Close() {
for _, searcher := range s.searchers {
searcher.Close()
}
}

View File

@ -0,0 +1,104 @@
// 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 search
import (
"testing"
"github.com/couchbaselabs/bleve/index"
)
func TestTermConjunctionSearch(t *testing.T) {
tests := []struct {
index index.Index
query *TermConjunctionQuery
results []*DocumentMatch
}{
{
index: twoDocIndex,
query: &TermConjunctionQuery{
Terms: []Query{
&TermQuery{
Term: "beer",
Field: "desc",
BoostVal: 1.0,
Explain: true,
},
&TermQuery{
Term: "marty",
Field: "name",
BoostVal: 5.0,
Explain: true,
},
},
Explain: true,
},
results: []*DocumentMatch{
&DocumentMatch{
ID: "1",
Score: 2.0097428702814377,
},
},
},
{
index: twoDocIndex,
query: &TermConjunctionQuery{
Terms: []Query{
&TermQuery{
Term: "angst",
Field: "desc",
BoostVal: 1.0,
Explain: true,
},
&TermQuery{
Term: "beer",
Field: "desc",
BoostVal: 1.0,
Explain: true,
},
},
Explain: true,
},
results: []*DocumentMatch{
&DocumentMatch{
ID: "2",
Score: 1.0807601687084403,
},
},
},
}
for testIndex, test := range tests {
searcher, err := NewTermConjunctionSearcher(test.index, test.query)
defer searcher.Close()
next, err := searcher.Next()
i := 0
for err == nil && next != nil {
if i < len(test.results) {
if next.ID != test.results[i].ID {
t.Errorf("expected result %d to have id %s got %s for test %d", i, test.results[i].ID, next.ID, testIndex)
}
if next.Score != test.results[i].Score {
t.Errorf("expected result %d to have score %v got %v for test %d", i, test.results[i].Score, next.Score, testIndex)
t.Logf("scoring explanation: %s", next.Expl)
}
}
next, err = searcher.Next()
i++
}
if err != nil {
t.Fatalf("error iterating searcher: %v for test %d", err, testIndex)
}
if len(test.results) != i {
t.Errorf("expected %d results got %d for test %d", len(test.results), i, testIndex)
}
}
}

36
search/util.go Normal file
View File

@ -0,0 +1,36 @@
// 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 search
func mergeLocations(locations []FieldTermLocationMap) FieldTermLocationMap {
rv := locations[0]
for i := 1; i < len(locations); i++ {
nextLocations := locations[i]
for field, termLocationMap := range nextLocations {
rvTermLocationMap, rvHasField := rv[field]
if rvHasField {
rv[field] = mergeTermLocationMaps(rvTermLocationMap, termLocationMap)
} else {
rv[field] = termLocationMap
}
}
}
return rv
}
func mergeTermLocationMaps(rv, other TermLocationMap) TermLocationMap {
for term, locationMap := range other {
// for a given term/document there cannot be different locations
// if they can back from different clauses, overwrite is ok
rv[term] = locationMap
}
return rv
}