Make facets much faster
This commit is contained in:
parent
412d50f1d7
commit
9a9b630a6d
|
@ -77,8 +77,10 @@ type IndexReader interface {
|
|||
|
||||
Document(id string) (*document.Document, error)
|
||||
DocumentFieldTerms(id string) (FieldTerms, error)
|
||||
DocumentFieldTermsForFields(id string, fieldIDs []uint16, fields []string) (FieldTerms, error)
|
||||
|
||||
Fields() ([]string, error)
|
||||
FieldIDs(fields []string) ([]uint16, error)
|
||||
|
||||
GetInternal(key []byte) ([]byte, error)
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/blevesearch/bleve/document"
|
||||
"github.com/blevesearch/bleve/index"
|
||||
"github.com/blevesearch/bleve/index/store"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type IndexReader struct {
|
||||
|
@ -110,6 +111,27 @@ func (i *IndexReader) DocumentFieldTerms(id string) (index.FieldTerms, error) {
|
|||
return rv, nil
|
||||
}
|
||||
|
||||
func (i *IndexReader) DocumentFieldTermsForFields(id string, fieldIDs []uint16, fields []string) (index.FieldTerms, error) {
|
||||
back, err := i.index.backIndexRowForDoc(i.kvreader, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rv := make(index.FieldTerms, len(fieldIDs))
|
||||
for _, entry := range back.termEntries {
|
||||
for id, field := range fieldIDs {
|
||||
if field == uint16(*entry.Field) {
|
||||
terms, ok := rv[fields[id]]
|
||||
if !ok {
|
||||
terms = make([]string, 0)
|
||||
}
|
||||
terms = append(terms, *entry.Term)
|
||||
rv[fields[id]] = terms
|
||||
}
|
||||
}
|
||||
}
|
||||
return rv, nil
|
||||
}
|
||||
|
||||
func (i *IndexReader) Fields() (fields []string, err error) {
|
||||
fields = make([]string, 0)
|
||||
it := i.kvreader.PrefixIterator([]byte{'f'})
|
||||
|
@ -139,6 +161,17 @@ func (i *IndexReader) Fields() (fields []string, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (i *IndexReader) FieldIDs(fields []string) (ids []uint16, err error) {
|
||||
for _, f := range fields {
|
||||
id, found := i.index.fieldCache.FieldNamed(f, false)
|
||||
if !found {
|
||||
return nil, fmt.Errorf("Field %s was not found in cache", f)
|
||||
}
|
||||
ids = append(ids, id)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (i *IndexReader) GetInternal(key []byte) ([]byte, error) {
|
||||
internalRow := NewInternalRow(key, nil)
|
||||
return i.kvreader.Get(internalRow.Key())
|
||||
|
|
16
search.go
16
search.go
|
@ -191,6 +191,8 @@ func (h *HighlightRequest) AddField(field string) {
|
|||
// Facets describe the set of facets to be computed.
|
||||
// Explain triggers inclusion of additional search
|
||||
// result score explanations.
|
||||
// Sort specifies the sorting for the returned results
|
||||
// results will be sorted by score if this is empty
|
||||
//
|
||||
// A special field named "*" can be used to return all fields.
|
||||
type SearchRequest struct {
|
||||
|
@ -201,6 +203,7 @@ type SearchRequest struct {
|
|||
Fields []string `json:"fields"`
|
||||
Facets FacetsRequest `json:"facets"`
|
||||
Explain bool `json:"explain"`
|
||||
Sort map[string]bool `json:"sort"`
|
||||
}
|
||||
|
||||
func (sr *SearchRequest) Validate() error {
|
||||
|
@ -220,6 +223,14 @@ func (r *SearchRequest) AddFacet(facetName string, f *FacetRequest) {
|
|||
r.Facets[facetName] = f
|
||||
}
|
||||
|
||||
// AddSort field in ascending or descending direction
|
||||
func (r *SearchRequest) AddSort(field string, ascending bool) {
|
||||
if r.Sort == nil {
|
||||
r.Sort = make(map[string]bool)
|
||||
}
|
||||
r.Sort[field] = ascending
|
||||
}
|
||||
|
||||
// UnmarshalJSON deserializes a JSON representation of
|
||||
// a SearchRequest
|
||||
func (r *SearchRequest) UnmarshalJSON(input []byte) error {
|
||||
|
@ -231,6 +242,7 @@ func (r *SearchRequest) UnmarshalJSON(input []byte) error {
|
|||
Fields []string `json:"fields"`
|
||||
Facets FacetsRequest `json:"facets"`
|
||||
Explain bool `json:"explain"`
|
||||
Sort map[string]bool `json:"sort"`
|
||||
}
|
||||
|
||||
err := json.Unmarshal(input, &temp)
|
||||
|
@ -248,6 +260,7 @@ func (r *SearchRequest) UnmarshalJSON(input []byte) error {
|
|||
r.Highlight = temp.Highlight
|
||||
r.Fields = temp.Fields
|
||||
r.Facets = temp.Facets
|
||||
r.Sort = temp.Sort
|
||||
r.Query, err = ParseQuery(temp.Q)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -280,6 +293,7 @@ func NewSearchRequestOptions(q Query, size, from int, explain bool) *SearchReque
|
|||
Size: size,
|
||||
From: from,
|
||||
Explain: explain,
|
||||
Sort: make(map[string]bool),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -307,7 +321,7 @@ func (iem IndexErrMap) UnmarshalJSON(data []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// SearchStatus is a secion in the SearchResult reporting how many
|
||||
// SearchStatus is a section in the SearchResult reporting how many
|
||||
// underlying indexes were queried, how many were successful/failed
|
||||
// and a map of any errors that were encountered
|
||||
type SearchStatus struct {
|
||||
|
|
|
@ -49,6 +49,10 @@ func (fb *DateTimeFacetBuilder) AddRange(name string, start, end time.Time) {
|
|||
fb.ranges[name] = &r
|
||||
}
|
||||
|
||||
func (fb *DateTimeFacetBuilder) Field() string {
|
||||
return fb.field
|
||||
}
|
||||
|
||||
func (fb *DateTimeFacetBuilder) Update(ft index.FieldTerms) {
|
||||
terms, ok := ft[fb.field]
|
||||
if ok {
|
||||
|
|
|
@ -48,6 +48,10 @@ func (fb *NumericFacetBuilder) AddRange(name string, min, max *float64) {
|
|||
fb.ranges[name] = &r
|
||||
}
|
||||
|
||||
func (fb *NumericFacetBuilder) Field() string {
|
||||
return fb.field
|
||||
}
|
||||
|
||||
func (fb *NumericFacetBuilder) Update(ft index.FieldTerms) {
|
||||
terms, ok := ft[fb.field]
|
||||
if ok {
|
||||
|
|
|
@ -32,6 +32,10 @@ func NewTermsFacetBuilder(field string, size int) *TermsFacetBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
func (fb *TermsFacetBuilder) Field() string {
|
||||
return fb.field
|
||||
}
|
||||
|
||||
func (fb *TermsFacetBuilder) Update(ft index.FieldTerms) {
|
||||
terms, ok := ft[fb.field]
|
||||
if ok {
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
type FacetBuilder interface {
|
||||
Update(index.FieldTerms)
|
||||
Result() *FacetResult
|
||||
Field() string
|
||||
}
|
||||
|
||||
type FacetsBuilder struct {
|
||||
|
@ -37,7 +38,15 @@ func (fb *FacetsBuilder) Add(name string, facetBuilder FacetBuilder) {
|
|||
}
|
||||
|
||||
func (fb *FacetsBuilder) Update(docMatch *DocumentMatch) error {
|
||||
fieldTerms, err := fb.indexReader.DocumentFieldTerms(docMatch.ID)
|
||||
var fields []string
|
||||
for _, facetBuilder := range fb.facets {
|
||||
fields = append(fields, facetBuilder.Field())
|
||||
}
|
||||
fieldIds, err := fb.indexReader.FieldIDs(fields)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fieldTerms, err := fb.indexReader.DocumentFieldTermsForFields(docMatch.ID, fieldIds, fields)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue