diff --git a/search/collectors/slice.go b/search/collectors/slice.go new file mode 100644 index 00000000..24eba815 --- /dev/null +++ b/search/collectors/slice.go @@ -0,0 +1,63 @@ +// 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 collectors + +import "github.com/blevesearch/bleve/search" + +type collectStoreSlice struct { + slice search.DocumentMatchCollection + compare collectorCompare +} + +func newStoreSlice(cap int, compare collectorCompare) *collectStoreSlice { + rv := &collectStoreSlice{ + slice: make(search.DocumentMatchCollection, 0, cap), + compare: compare, + } + return rv +} + +func (c *collectStoreSlice) Add(doc *search.DocumentMatch) { + // find where to insert, starting at end (lowest) + i := len(c.slice) + for ; i > 0; i-- { + cmp := c.compare(doc, c.slice[i-1]) + if cmp >= 0 { + break + } + } + if i < 0 { + i = 0 + } + // insert at i + c.slice = append(c.slice, nil) + copy(c.slice[i+1:], c.slice[i:]) + c.slice[i] = doc +} + +func (c *collectStoreSlice) RemoveLast() *search.DocumentMatch { + var rv *search.DocumentMatch + rv, c.slice = c.slice[len(c.slice)-1], c.slice[:len(c.slice)-1] + return rv +} + +func (c *collectStoreSlice) Final(skip int, fixup collectorFixup) (search.DocumentMatchCollection, error) { + for i := skip; i < len(c.slice); i++ { + err := fixup(c.slice[i]) + if err != nil { + return nil, err + } + } + return c.slice[skip:], nil +} + +func (c *collectStoreSlice) Len() int { + return len(c.slice) +} diff --git a/search/collectors/topn.go b/search/collectors/topn.go index 15ce77c8..636b7593 100644 --- a/search/collectors/topn.go +++ b/search/collectors/topn.go @@ -32,7 +32,7 @@ type TopNCollector struct { results search.DocumentMatchCollection facetsBuilder *search.FacetsBuilder - store *collectStoreList + store *collectStoreSlice needDocIds bool neededFields []string @@ -52,7 +52,7 @@ func NewTopNCollector(size int, skip int, sort search.SortOrder) *TopNCollector hc := &TopNCollector{size: size, skip: skip, sort: sort} // pre-allocate space on the heap, we need size+skip results // +1 additional while figuring out which to evict - hc.store = newStoreList(size+skip+1, func(i, j *search.DocumentMatch) int { + hc.store = newStoreSlice(size+skip+1, func(i, j *search.DocumentMatch) int { return hc.sort.Compare(hc.cachedScoring, hc.cachedDesc, i, j) })