From 79cc39a67eee0ee01c2e7df586813a2801503701 Mon Sep 17 00:00:00 2001 From: Marty Schoch Date: Sun, 18 Sep 2016 09:33:18 -0400 Subject: [PATCH] refactor mapping to inteface and move into separate package the index mapping contains some relatively messy logic and the top-level bleve package only cares about a relatively small portion of this the motivation for this change is to codify the part that the top-level bleve package cares about into an interface then move all the details into its own package NOTE: the top-level bleve package still has hard dependency on the actual implementation (for now) because it must deserialize mappings from JSON and simply assumes it is this one instance. this is seen as OK for now, and this issue could be revisited in a future change. moving the logic into a separate package is seen as a simplification of top-level bleve, even though we still depend on the one particular implementation. --- examples_test.go | 7 +- http/index_get.go | 8 +- index.go | 22 +--- index_alias_impl.go | 3 +- index_alias_impl_test.go | 3 +- index_impl.go | 15 ++- index_test.go | 3 +- mapping.go | 56 ++++++++ mapping/analysis.go | 94 +++++++++++++ mapping_document.go => mapping/document.go | 4 +- mapping_field.go => mapping/field.go | 14 +- mapping_index.go => mapping/index.go | 145 +++++---------------- mapping/mapping.go | 44 +++++++ mapping_test.go => mapping/mapping_test.go | 42 +++--- reflect.go => mapping/reflect.go | 2 +- query.go | 7 +- query_bool_field.go | 5 +- query_boolean.go | 3 +- query_conjunction.go | 3 +- query_date_range.go | 5 +- query_disjunction.go | 3 +- query_docid.go | 3 +- query_fuzzy.go | 5 +- query_match.go | 9 +- query_match_all.go | 3 +- query_match_none.go | 3 +- query_match_phrase.go | 9 +- query_numeric_range.go | 5 +- query_phrase.go | 3 +- query_prefix.go | 5 +- query_regexp.go | 5 +- query_string.go | 3 +- query_string_parser_test.go | 4 +- query_term.go | 5 +- query_test.go | 2 +- query_wildcard.go | 5 +- test/integration_test.go | 3 +- 37 files changed, 348 insertions(+), 212 deletions(-) create mode 100644 mapping.go create mode 100644 mapping/analysis.go rename mapping_document.go => mapping/document.go (99%) rename mapping_field.go => mapping/field.go (95%) rename mapping_index.go => mapping/index.go (73%) create mode 100644 mapping/mapping.go rename mapping_test.go => mapping/mapping_test.go (95%) rename reflect.go => mapping/reflect.go (99%) diff --git a/examples_test.go b/examples_test.go index a0e8e097..82ac57fa 100644 --- a/examples_test.go +++ b/examples_test.go @@ -15,11 +15,12 @@ import ( "testing" "time" + "github.com/blevesearch/bleve/mapping" "github.com/blevesearch/bleve/search" "github.com/blevesearch/bleve/search/highlight/highlighters/ansi" ) -var mapping *IndexMapping +var indexMapping mapping.IndexMapping var example_index Index var err error @@ -43,8 +44,8 @@ func TestMain(m *testing.M) { } func ExampleNew() { - mapping = NewIndexMapping() - example_index, err = New("path_to_index", mapping) + indexMapping = NewIndexMapping() + example_index, err = New("path_to_index", indexMapping) if err != nil { panic(err) } diff --git a/http/index_get.go b/http/index_get.go index 360e2cd6..7b77900c 100644 --- a/http/index_get.go +++ b/http/index_get.go @@ -13,7 +13,7 @@ import ( "fmt" "net/http" - "github.com/blevesearch/bleve" + "github.com/blevesearch/bleve/mapping" ) type GetIndexHandler struct { @@ -42,9 +42,9 @@ func (h *GetIndexHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { } rv := struct { - Status string `json:"status"` - Name string `json:"name"` - Mapping *bleve.IndexMapping `json:"mapping"` + Status string `json:"status"` + Name string `json:"name"` + Mapping mapping.IndexMapping `json:"mapping"` }{ Status: "ok", Name: indexName, diff --git a/index.go b/index.go index df708c62..fafea12e 100644 --- a/index.go +++ b/index.go @@ -13,6 +13,7 @@ import ( "github.com/blevesearch/bleve/document" "github.com/blevesearch/bleve/index" "github.com/blevesearch/bleve/index/store" + "github.com/blevesearch/bleve/mapping" "golang.org/x/net/context" ) @@ -35,7 +36,7 @@ func (b *Batch) Index(id string, data interface{}) error { return ErrorEmptyID } doc := document.NewDocument(id) - err := b.index.Mapping().mapDocument(doc, data) + err := b.index.Mapping().MapDocument(doc, data) if err != nil { return err } @@ -92,11 +93,6 @@ func (b *Batch) Reset() { // assigns string paths to its fields or values then applies field mappings on // them. // -// If the value is a []byte, the indexer attempts to convert it to something -// else using the ByteArrayConverter registered as -// IndexMapping.ByteArrayConverter. By default, it interprets the value as a -// JSON payload and unmarshals it to map[string]interface{}. -// // The DocumentMapping used to index a value is deduced by the following rules: // 1) If value implements Classifier interface, resolve the mapping from Type(). // 2) If value has a string field or value at IndexMapping.TypeField. @@ -178,7 +174,7 @@ type Index interface { Close() error - Mapping() *IndexMapping + Mapping() mapping.IndexMapping Stats() *IndexStat StatsMap() map[string]interface{} @@ -197,16 +193,10 @@ type Index interface { Advanced() (index.Index, store.KVStore, error) } -// A Classifier is an interface describing any object -// which knows how to identify its own type. -type Classifier interface { - Type() string -} - // New index at the specified path, must not exist. // The provided mapping will be used for all // Index/Search operations. -func New(path string, mapping *IndexMapping) (Index, error) { +func New(path string, mapping mapping.IndexMapping) (Index, error) { return newIndexUsing(path, mapping, Config.DefaultIndexType, Config.DefaultKVStore, nil) } @@ -215,7 +205,7 @@ func New(path string, mapping *IndexMapping) (Index, error) { // and will be lost once closed. // The provided mapping will be used for all // Index/Search operations. -func NewMemOnly(mapping *IndexMapping) (Index, error) { +func NewMemOnly(mapping mapping.IndexMapping) (Index, error) { return newIndexUsing("", mapping, Config.DefaultIndexType, Config.DefaultMemKVStore, nil) } @@ -227,7 +217,7 @@ func NewMemOnly(mapping *IndexMapping) (Index, error) { // The specified kvstore implementation will be used // and the provided kvconfig will be passed to its // constructor. -func NewUsing(path string, mapping *IndexMapping, indexType string, kvstore string, kvconfig map[string]interface{}) (Index, error) { +func NewUsing(path string, mapping mapping.IndexMapping, indexType string, kvstore string, kvconfig map[string]interface{}) (Index, error) { return newIndexUsing(path, mapping, indexType, kvstore, kvconfig) } diff --git a/index_alias_impl.go b/index_alias_impl.go index ea3d6fb5..a379efb0 100644 --- a/index_alias_impl.go +++ b/index_alias_impl.go @@ -19,6 +19,7 @@ import ( "github.com/blevesearch/bleve/document" "github.com/blevesearch/bleve/index" "github.com/blevesearch/bleve/index/store" + "github.com/blevesearch/bleve/mapping" "github.com/blevesearch/bleve/search" ) @@ -259,7 +260,7 @@ func (i *indexAliasImpl) Close() error { return nil } -func (i *indexAliasImpl) Mapping() *IndexMapping { +func (i *indexAliasImpl) Mapping() mapping.IndexMapping { i.mutex.RLock() defer i.mutex.RUnlock() diff --git a/index_alias_impl_test.go b/index_alias_impl_test.go index b45a312e..92a48fb0 100644 --- a/index_alias_impl_test.go +++ b/index_alias_impl_test.go @@ -11,6 +11,7 @@ import ( "github.com/blevesearch/bleve/document" "github.com/blevesearch/bleve/index" "github.com/blevesearch/bleve/index/store" + "github.com/blevesearch/bleve/mapping" "github.com/blevesearch/bleve/numeric_util" "github.com/blevesearch/bleve/search" ) @@ -1269,7 +1270,7 @@ func (i *stubIndex) Close() error { return i.err } -func (i *stubIndex) Mapping() *IndexMapping { +func (i *stubIndex) Mapping() mapping.IndexMapping { return nil } diff --git a/index_impl.go b/index_impl.go index aae26a0b..1d581cc0 100644 --- a/index_impl.go +++ b/index_impl.go @@ -23,6 +23,7 @@ import ( "github.com/blevesearch/bleve/index" "github.com/blevesearch/bleve/index/store" "github.com/blevesearch/bleve/index/upside_down" + "github.com/blevesearch/bleve/mapping" "github.com/blevesearch/bleve/registry" "github.com/blevesearch/bleve/search" "github.com/blevesearch/bleve/search/collectors" @@ -35,7 +36,7 @@ type indexImpl struct { name string meta *indexMeta i index.Index - m *IndexMapping + m mapping.IndexMapping mutex sync.RWMutex open bool stats *IndexStat @@ -49,7 +50,7 @@ func indexStorePath(path string) string { return path + string(os.PathSeparator) + storePath } -func newIndexUsing(path string, mapping *IndexMapping, indexType string, kvstore string, kvconfig map[string]interface{}) (*indexImpl, error) { +func newIndexUsing(path string, mapping mapping.IndexMapping, indexType string, kvstore string, kvconfig map[string]interface{}) (*indexImpl, error) { // first validate the mapping err := mapping.Validate() if err != nil { @@ -183,7 +184,7 @@ func openIndexUsing(path string, runtimeConfig map[string]interface{}) (rv *inde return nil, err } - var im IndexMapping + var im *mapping.IndexMappingImpl err = json.Unmarshal(mappingBytes, &im) if err != nil { return nil, fmt.Errorf("error parsing mapping JSON: %v\nmapping contents:\n%s", err, string(mappingBytes)) @@ -202,7 +203,7 @@ func openIndexUsing(path string, runtimeConfig map[string]interface{}) (rv *inde return rv, err } - rv.m = &im + rv.m = im indexStats.Register(rv) return rv, err } @@ -219,7 +220,7 @@ func (i *indexImpl) Advanced() (index.Index, store.KVStore, error) { // Mapping returns the IndexMapping in use by this // Index. -func (i *indexImpl) Mapping() *IndexMapping { +func (i *indexImpl) Mapping() mapping.IndexMapping { return i.m } @@ -239,7 +240,7 @@ func (i *indexImpl) Index(id string, data interface{}) (err error) { } doc := document.NewDocument(id) - err = i.m.mapDocument(doc, data) + err = i.m.MapDocument(doc, data) if err != nil { return } @@ -387,7 +388,7 @@ func (i *indexImpl) SearchInContext(ctx context.Context, req *SearchRequest) (sr } else if facetRequest.DateTimeRanges != nil { // build date range facet facetBuilder := facets.NewDateTimeFacetBuilder(facetRequest.Field, facetRequest.Size) - dateTimeParser := i.m.dateTimeParserNamed(i.m.DefaultDateTimeParser) + dateTimeParser := i.m.DateTimeParserNamed("") for _, dr := range facetRequest.DateTimeRanges { dr.ParseDates(dateTimeParser) facetBuilder.AddRange(dr.Name, dr.Start, dr.End) diff --git a/index_test.go b/index_test.go index 9fdeb175..05341f99 100644 --- a/index_test.go +++ b/index_test.go @@ -29,6 +29,7 @@ import ( "github.com/blevesearch/bleve/analysis/analyzers/keyword_analyzer" "github.com/blevesearch/bleve/index" "github.com/blevesearch/bleve/index/store/null" + "github.com/blevesearch/bleve/mapping" "github.com/blevesearch/bleve/search" ) @@ -365,7 +366,7 @@ func (s *slowQuery) SetField(f string) Query { return s.actual.SetField(f) } -func (s *slowQuery) Searcher(i index.IndexReader, m *IndexMapping, explain bool) (search.Searcher, error) { +func (s *slowQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) { time.Sleep(s.delay) return s.actual.Searcher(i, m, explain) } diff --git a/mapping.go b/mapping.go new file mode 100644 index 00000000..e1ce7242 --- /dev/null +++ b/mapping.go @@ -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 bleve + +import "github.com/blevesearch/bleve/mapping" + +// NewIndexMapping creates a new IndexMapping that will use all the default indexing rules +func NewIndexMapping() *mapping.IndexMappingImpl { + return mapping.NewIndexMapping() +} + +// NewDocumentMapping returns a new document mapping +// with all the default values. +func NewDocumentMapping() *mapping.DocumentMapping { + return mapping.NewDocumentMapping() +} + +// NewDocumentStaticMapping returns a new document +// mapping that will not automatically index parts +// of a document without an explicit mapping. +func NewDocumentStaticMapping() *mapping.DocumentMapping { + return mapping.NewDocumentStaticMapping() +} + +// NewDocumentDisabledMapping returns a new document +// mapping that will not perform any indexing. +func NewDocumentDisabledMapping() *mapping.DocumentMapping { + return mapping.NewDocumentDisabledMapping() +} + +// NewTextFieldMapping returns a default field mapping for text +func NewTextFieldMapping() *mapping.FieldMapping { + return mapping.NewTextFieldMapping() +} + +// NewNumericFieldMapping returns a default field mapping for numbers +func NewNumericFieldMapping() *mapping.FieldMapping { + return mapping.NewNumericFieldMapping() +} + +// NewDateTimeFieldMapping returns a default field mapping for dates +func NewDateTimeFieldMapping() *mapping.FieldMapping { + return mapping.NewDateTimeFieldMapping() +} + +// NewBooleanFieldMapping returns a default field mapping for booleans +func NewBooleanFieldMapping() *mapping.FieldMapping { + return mapping.NewBooleanFieldMapping() +} diff --git a/mapping/analysis.go b/mapping/analysis.go new file mode 100644 index 00000000..9ff56553 --- /dev/null +++ b/mapping/analysis.go @@ -0,0 +1,94 @@ +// 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 mapping + +type customAnalysis struct { + CharFilters map[string]map[string]interface{} `json:"char_filters,omitempty"` + Tokenizers map[string]map[string]interface{} `json:"tokenizers,omitempty"` + TokenMaps map[string]map[string]interface{} `json:"token_maps,omitempty"` + TokenFilters map[string]map[string]interface{} `json:"token_filters,omitempty"` + Analyzers map[string]map[string]interface{} `json:"analyzers,omitempty"` + DateTimeParsers map[string]map[string]interface{} `json:"date_time_parsers,omitempty"` +} + +func (c *customAnalysis) registerAll(i *IndexMappingImpl) error { + for name, config := range c.CharFilters { + _, err := i.cache.DefineCharFilter(name, config) + if err != nil { + return err + } + } + + if len(c.Tokenizers) > 0 { + // put all the names in map tracking work to do + todo := map[string]struct{}{} + for name := range c.Tokenizers { + todo[name] = struct{}{} + } + registered := 1 + errs := []error{} + // as long as we keep making progress, keep going + for len(todo) > 0 && registered > 0 { + registered = 0 + errs = []error{} + for name := range todo { + config := c.Tokenizers[name] + _, err := i.cache.DefineTokenizer(name, config) + if err != nil { + errs = append(errs, err) + } else { + delete(todo, name) + registered++ + } + } + } + + if len(errs) > 0 { + return errs[0] + } + } + for name, config := range c.TokenMaps { + _, err := i.cache.DefineTokenMap(name, config) + if err != nil { + return err + } + } + for name, config := range c.TokenFilters { + _, err := i.cache.DefineTokenFilter(name, config) + if err != nil { + return err + } + } + for name, config := range c.Analyzers { + _, err := i.cache.DefineAnalyzer(name, config) + if err != nil { + return err + } + } + for name, config := range c.DateTimeParsers { + _, err := i.cache.DefineDateTimeParser(name, config) + if err != nil { + return err + } + } + return nil +} + +func newCustomAnalysis() *customAnalysis { + rv := customAnalysis{ + CharFilters: make(map[string]map[string]interface{}), + Tokenizers: make(map[string]map[string]interface{}), + TokenMaps: make(map[string]map[string]interface{}), + TokenFilters: make(map[string]map[string]interface{}), + Analyzers: make(map[string]map[string]interface{}), + DateTimeParsers: make(map[string]map[string]interface{}), + } + return &rv +} diff --git a/mapping_document.go b/mapping/document.go similarity index 99% rename from mapping_document.go rename to mapping/document.go index 5bea75aa..19d04210 100644 --- a/mapping_document.go +++ b/mapping/document.go @@ -7,7 +7,7 @@ // either express or implied. See the License for the specific language governing permissions // and limitations under the License. -package bleve +package mapping import ( "encoding/json" @@ -405,7 +405,7 @@ func (dm *DocumentMapping) processProperty(property interface{}, path []string, // automatic indexing behavior // first see if it can be parsed by the default date parser - dateTimeParser := context.im.dateTimeParserNamed(context.im.DefaultDateTimeParser) + dateTimeParser := context.im.DateTimeParserNamed(context.im.DefaultDateTimeParser) if dateTimeParser != nil { parsedDateTime, err := dateTimeParser.ParseDateTime(propertyValueString) if err != nil { diff --git a/mapping_field.go b/mapping/field.go similarity index 95% rename from mapping_field.go rename to mapping/field.go index 1a310b3a..58cac1fc 100644 --- a/mapping_field.go +++ b/mapping/field.go @@ -7,7 +7,7 @@ // either express or implied. See the License for the specific language governing permissions // and limitations under the License. -package bleve +package mapping import ( "encoding/json" @@ -61,7 +61,7 @@ func NewTextFieldMapping() *FieldMapping { } } -func newTextFieldMappingDynamic(im *IndexMapping) *FieldMapping { +func newTextFieldMappingDynamic(im *IndexMappingImpl) *FieldMapping { rv := NewTextFieldMapping() rv.Store = im.StoreDynamic rv.Index = im.IndexDynamic @@ -78,7 +78,7 @@ func NewNumericFieldMapping() *FieldMapping { } } -func newNumericFieldMappingDynamic(im *IndexMapping) *FieldMapping { +func newNumericFieldMappingDynamic(im *IndexMappingImpl) *FieldMapping { rv := NewNumericFieldMapping() rv.Store = im.StoreDynamic rv.Index = im.IndexDynamic @@ -95,7 +95,7 @@ func NewDateTimeFieldMapping() *FieldMapping { } } -func newDateTimeFieldMappingDynamic(im *IndexMapping) *FieldMapping { +func newDateTimeFieldMappingDynamic(im *IndexMappingImpl) *FieldMapping { rv := NewDateTimeFieldMapping() rv.Store = im.StoreDynamic rv.Index = im.IndexDynamic @@ -112,7 +112,7 @@ func NewBooleanFieldMapping() *FieldMapping { } } -func newBooleanFieldMappingDynamic(im *IndexMapping) *FieldMapping { +func newBooleanFieldMappingDynamic(im *IndexMappingImpl) *FieldMapping { rv := NewBooleanFieldMapping() rv.Store = im.StoreDynamic rv.Index = im.IndexDynamic @@ -150,7 +150,7 @@ func (fm *FieldMapping) processString(propertyValueString string, pathString str if fm.DateFormat != "" { dateTimeFormat = fm.DateFormat } - dateTimeParser := context.im.dateTimeParserNamed(dateTimeFormat) + dateTimeParser := context.im.DateTimeParserNamed(dateTimeFormat) if dateTimeParser != nil { parsedDateTime, err := dateTimeParser.ParseDateTime(propertyValueString) if err == nil { @@ -211,7 +211,7 @@ func (fm *FieldMapping) analyzerForField(path []string, context *walkContext) *a analyzerName = context.im.DefaultAnalyzer } } - return context.im.analyzerNamed(analyzerName) + return context.im.AnalyzerNamed(analyzerName) } func getFieldName(pathString string, path []string, fieldMapping *FieldMapping) string { diff --git a/mapping_index.go b/mapping/index.go similarity index 73% rename from mapping_index.go rename to mapping/index.go index d91b0751..84e0e479 100644 --- a/mapping_index.go +++ b/mapping/index.go @@ -7,7 +7,7 @@ // either express or implied. See the License for the specific language governing permissions // and limitations under the License. -package bleve +package mapping import ( "encoding/json" @@ -28,98 +28,14 @@ const defaultField = "_all" const defaultAnalyzer = standard_analyzer.Name const defaultDateTimeParser = datetime_optional.Name -type customAnalysis struct { - CharFilters map[string]map[string]interface{} `json:"char_filters,omitempty"` - Tokenizers map[string]map[string]interface{} `json:"tokenizers,omitempty"` - TokenMaps map[string]map[string]interface{} `json:"token_maps,omitempty"` - TokenFilters map[string]map[string]interface{} `json:"token_filters,omitempty"` - Analyzers map[string]map[string]interface{} `json:"analyzers,omitempty"` - DateTimeParsers map[string]map[string]interface{} `json:"date_time_parsers,omitempty"` -} - -func (c *customAnalysis) registerAll(i *IndexMapping) error { - for name, config := range c.CharFilters { - _, err := i.cache.DefineCharFilter(name, config) - if err != nil { - return err - } - } - - if len(c.Tokenizers) > 0 { - // put all the names in map tracking work to do - todo := map[string]struct{}{} - for name := range c.Tokenizers { - todo[name] = struct{}{} - } - registered := 1 - errs := []error{} - // as long as we keep making progress, keep going - for len(todo) > 0 && registered > 0 { - registered = 0 - errs = []error{} - for name := range todo { - config := c.Tokenizers[name] - _, err := i.cache.DefineTokenizer(name, config) - if err != nil { - errs = append(errs, err) - } else { - delete(todo, name) - registered++ - } - } - } - - if len(errs) > 0 { - return errs[0] - } - } - for name, config := range c.TokenMaps { - _, err := i.cache.DefineTokenMap(name, config) - if err != nil { - return err - } - } - for name, config := range c.TokenFilters { - _, err := i.cache.DefineTokenFilter(name, config) - if err != nil { - return err - } - } - for name, config := range c.Analyzers { - _, err := i.cache.DefineAnalyzer(name, config) - if err != nil { - return err - } - } - for name, config := range c.DateTimeParsers { - _, err := i.cache.DefineDateTimeParser(name, config) - if err != nil { - return err - } - } - return nil -} - -func newCustomAnalysis() *customAnalysis { - rv := customAnalysis{ - CharFilters: make(map[string]map[string]interface{}), - Tokenizers: make(map[string]map[string]interface{}), - TokenMaps: make(map[string]map[string]interface{}), - TokenFilters: make(map[string]map[string]interface{}), - Analyzers: make(map[string]map[string]interface{}), - DateTimeParsers: make(map[string]map[string]interface{}), - } - return &rv -} - -// An IndexMapping controls how objects are placed +// An IndexMappingImpl controls how objects are placed // into an index. // First the type of the object is determined. // Once the type is know, the appropriate // DocumentMapping is selected by the type. // If no mapping was determined for that type, // a DefaultMapping will be used. -type IndexMapping struct { +type IndexMappingImpl struct { TypeMapping map[string]*DocumentMapping `json:"types,omitempty"` DefaultMapping *DocumentMapping `json:"default_mapping"` TypeField string `json:"type_field"` @@ -134,7 +50,7 @@ type IndexMapping struct { } // AddCustomCharFilter defines a custom char filter for use in this mapping -func (im *IndexMapping) AddCustomCharFilter(name string, config map[string]interface{}) error { +func (im *IndexMappingImpl) AddCustomCharFilter(name string, config map[string]interface{}) error { _, err := im.cache.DefineCharFilter(name, config) if err != nil { return err @@ -144,7 +60,7 @@ func (im *IndexMapping) AddCustomCharFilter(name string, config map[string]inter } // AddCustomTokenizer defines a custom tokenizer for use in this mapping -func (im *IndexMapping) AddCustomTokenizer(name string, config map[string]interface{}) error { +func (im *IndexMappingImpl) AddCustomTokenizer(name string, config map[string]interface{}) error { _, err := im.cache.DefineTokenizer(name, config) if err != nil { return err @@ -154,7 +70,7 @@ func (im *IndexMapping) AddCustomTokenizer(name string, config map[string]interf } // AddCustomTokenMap defines a custom token map for use in this mapping -func (im *IndexMapping) AddCustomTokenMap(name string, config map[string]interface{}) error { +func (im *IndexMappingImpl) AddCustomTokenMap(name string, config map[string]interface{}) error { _, err := im.cache.DefineTokenMap(name, config) if err != nil { return err @@ -164,7 +80,7 @@ func (im *IndexMapping) AddCustomTokenMap(name string, config map[string]interfa } // AddCustomTokenFilter defines a custom token filter for use in this mapping -func (im *IndexMapping) AddCustomTokenFilter(name string, config map[string]interface{}) error { +func (im *IndexMappingImpl) AddCustomTokenFilter(name string, config map[string]interface{}) error { _, err := im.cache.DefineTokenFilter(name, config) if err != nil { return err @@ -202,7 +118,7 @@ func (im *IndexMapping) AddCustomTokenFilter(name string, config map[string]inte // ... // }, // }) -func (im *IndexMapping) AddCustomAnalyzer(name string, config map[string]interface{}) error { +func (im *IndexMappingImpl) AddCustomAnalyzer(name string, config map[string]interface{}) error { _, err := im.cache.DefineAnalyzer(name, config) if err != nil { return err @@ -212,7 +128,7 @@ func (im *IndexMapping) AddCustomAnalyzer(name string, config map[string]interfa } // AddCustomDateTimeParser defines a custom date time parser for use in this mapping -func (im *IndexMapping) AddCustomDateTimeParser(name string, config map[string]interface{}) error { +func (im *IndexMappingImpl) AddCustomDateTimeParser(name string, config map[string]interface{}) error { _, err := im.cache.DefineDateTimeParser(name, config) if err != nil { return err @@ -222,8 +138,8 @@ func (im *IndexMapping) AddCustomDateTimeParser(name string, config map[string]i } // NewIndexMapping creates a new IndexMapping that will use all the default indexing rules -func NewIndexMapping() *IndexMapping { - return &IndexMapping{ +func NewIndexMapping() *IndexMappingImpl { + return &IndexMappingImpl{ TypeMapping: make(map[string]*DocumentMapping), DefaultMapping: NewDocumentMapping(), TypeField: defaultTypeField, @@ -240,7 +156,7 @@ func NewIndexMapping() *IndexMapping { // Validate will walk the entire structure ensuring the following // explicitly named and default analyzers can be built -func (im *IndexMapping) Validate() error { +func (im *IndexMappingImpl) Validate() error { _, err := im.cache.AnalyzerNamed(im.DefaultAnalyzer) if err != nil { return err @@ -263,11 +179,11 @@ func (im *IndexMapping) Validate() error { } // AddDocumentMapping sets a custom document mapping for the specified type -func (im *IndexMapping) AddDocumentMapping(doctype string, dm *DocumentMapping) { +func (im *IndexMappingImpl) AddDocumentMapping(doctype string, dm *DocumentMapping) { im.TypeMapping[doctype] = dm } -func (im *IndexMapping) mappingForType(docType string) *DocumentMapping { +func (im *IndexMappingImpl) mappingForType(docType string) *DocumentMapping { docMapping := im.TypeMapping[docType] if docMapping == nil { docMapping = im.DefaultMapping @@ -276,7 +192,7 @@ func (im *IndexMapping) mappingForType(docType string) *DocumentMapping { } // UnmarshalJSON offers custom unmarshaling with optional strict validation -func (im *IndexMapping) UnmarshalJSON(data []byte) error { +func (im *IndexMappingImpl) UnmarshalJSON(data []byte) error { var tmp map[string]json.RawMessage err := json.Unmarshal(data, &tmp) @@ -367,7 +283,7 @@ func (im *IndexMapping) UnmarshalJSON(data []byte) error { return nil } -func (im *IndexMapping) determineType(data interface{}) string { +func (im *IndexMappingImpl) determineType(data interface{}) string { // first see if the object implements Classifier classifier, ok := data.(Classifier) if ok { @@ -383,7 +299,7 @@ func (im *IndexMapping) determineType(data interface{}) string { return im.DefaultType } -func (im *IndexMapping) mapDocument(doc *document.Document, data interface{}) error { +func (im *IndexMappingImpl) MapDocument(doc *document.Document, data interface{}) error { docType := im.determineType(data) docMapping := im.mappingForType(docType) walkContext := im.newWalkContext(doc, docMapping) @@ -403,12 +319,12 @@ func (im *IndexMapping) mapDocument(doc *document.Document, data interface{}) er type walkContext struct { doc *document.Document - im *IndexMapping + im *IndexMappingImpl dm *DocumentMapping excludedFromAll []string } -func (im *IndexMapping) newWalkContext(doc *document.Document, dm *DocumentMapping) *walkContext { +func (im *IndexMappingImpl) newWalkContext(doc *document.Document, dm *DocumentMapping) *walkContext { return &walkContext{ doc: doc, im: im, @@ -422,7 +338,7 @@ func (im *IndexMapping) newWalkContext(doc *document.Document, dm *DocumentMappi // provided path, if one exists and it has an explicit analyzer // that is returned // nil should be an acceptable return value meaning we don't know -func (im *IndexMapping) analyzerNameForPath(path string) string { +func (im *IndexMappingImpl) AnalyzerNameForPath(path string) string { // first we look for explicit mapping on the field for _, docMapping := range im.TypeMapping { analyzerName := docMapping.analyzerNameForPath(path) @@ -452,7 +368,7 @@ func (im *IndexMapping) analyzerNameForPath(path string) string { return im.DefaultAnalyzer } -func (im *IndexMapping) analyzerNamed(name string) *analysis.Analyzer { +func (im *IndexMappingImpl) AnalyzerNamed(name string) *analysis.Analyzer { analyzer, err := im.cache.AnalyzerNamed(name) if err != nil { logger.Printf("error using analyzer named: %s", name) @@ -461,7 +377,10 @@ func (im *IndexMapping) analyzerNamed(name string) *analysis.Analyzer { return analyzer } -func (im *IndexMapping) dateTimeParserNamed(name string) analysis.DateTimeParser { +func (im *IndexMappingImpl) DateTimeParserNamed(name string) analysis.DateTimeParser { + if name == "" { + name = im.DefaultDateTimeParser + } dateTimeParser, err := im.cache.DateTimeParserNamed(name) if err != nil { logger.Printf("error using datetime parser named: %s", name) @@ -470,7 +389,7 @@ func (im *IndexMapping) dateTimeParserNamed(name string) analysis.DateTimeParser return dateTimeParser } -func (im *IndexMapping) datetimeParserNameForPath(path string) string { +func (im *IndexMappingImpl) datetimeParserNameForPath(path string) string { // first we look for explicit mapping on the field for _, docMapping := range im.TypeMapping { @@ -487,7 +406,7 @@ func (im *IndexMapping) datetimeParserNameForPath(path string) string { return im.DefaultDateTimeParser } -func (im *IndexMapping) AnalyzeText(analyzerName string, text []byte) (analysis.TokenStream, error) { +func (im *IndexMappingImpl) AnalyzeText(analyzerName string, text []byte) (analysis.TokenStream, error) { analyzer, err := im.cache.AnalyzerNamed(analyzerName) if err != nil { return nil, err @@ -496,6 +415,12 @@ func (im *IndexMapping) AnalyzeText(analyzerName string, text []byte) (analysis. } // FieldAnalyzer returns the name of the analyzer used on a field. -func (im *IndexMapping) FieldAnalyzer(field string) string { - return im.analyzerNameForPath(field) +func (im *IndexMappingImpl) FieldAnalyzer(field string) string { + return im.AnalyzerNameForPath(field) +} + +// wrapper to satisfy new interface + +func (im *IndexMappingImpl) DefaultSearchField() string { + return im.DefaultField } diff --git a/mapping/mapping.go b/mapping/mapping.go new file mode 100644 index 00000000..509a5380 --- /dev/null +++ b/mapping/mapping.go @@ -0,0 +1,44 @@ +// 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 mapping + +import ( + "io/ioutil" + "log" + + "github.com/blevesearch/bleve/analysis" + "github.com/blevesearch/bleve/document" +) + +// A Classifier is an interface describing any object +// which knows how to identify its own type. +type Classifier interface { + Type() string +} + +var logger = log.New(ioutil.Discard, "bleve mapping ", log.LstdFlags) + +// SetLog sets the logger used for logging +// by default log messages are sent to ioutil.Discard +func SetLog(l *log.Logger) { + logger = l +} + +type IndexMapping interface { + MapDocument(doc *document.Document, data interface{}) error + Validate() error + + DateTimeParserNamed(name string) analysis.DateTimeParser + + DefaultSearchField() string + + AnalyzerNameForPath(path string) string + AnalyzerNamed(name string) *analysis.Analyzer +} diff --git a/mapping_test.go b/mapping/mapping_test.go similarity index 95% rename from mapping_test.go rename to mapping/mapping_test.go index a5eda3df..6c9b7237 100644 --- a/mapping_test.go +++ b/mapping/mapping_test.go @@ -7,7 +7,7 @@ // either express or implied. See the License for the specific language governing permissions // and limitations under the License. -package bleve +package mapping import ( "encoding/json" @@ -46,7 +46,7 @@ var mappingSource = []byte(`{ "default_type": "_default" }`) -func buildMapping() *IndexMapping { +func buildMapping() IndexMapping { nameFieldMapping := NewTextFieldMapping() nameFieldMapping.Name = "name" nameFieldMapping.Analyzer = "standard" @@ -66,7 +66,7 @@ func buildMapping() *IndexMapping { func TestUnmarshalMappingJSON(t *testing.T) { mapping := buildMapping() - var indexMapping IndexMapping + var indexMapping IndexMappingImpl err := json.Unmarshal(mappingSource, &indexMapping) if err != nil { t.Fatal(err) @@ -88,7 +88,7 @@ func TestMappingStructWithJSONTags(t *testing.T) { } doc := document.NewDocument("1") - err := mapping.mapDocument(doc, x) + err := mapping.MapDocument(doc, x) if err != nil { t.Fatal(err) } @@ -128,7 +128,7 @@ func TestMappingStructWithJSONTagsOneDisabled(t *testing.T) { } doc := document.NewDocument("1") - err := mapping.mapDocument(doc, x) + err := mapping.MapDocument(doc, x) if err != nil { t.Fatal(err) } @@ -168,7 +168,7 @@ func TestMappingStructWithPointerToString(t *testing.T) { } doc := document.NewDocument("1") - err := mapping.mapDocument(doc, x) + err := mapping.MapDocument(doc, x) if err != nil { t.Fatal(err) } @@ -200,7 +200,7 @@ func TestMappingJSONWithNull(t *testing.T) { } doc := document.NewDocument("1") - err = mapping.mapDocument(doc, jsondoc) + err = mapping.MapDocument(doc, jsondoc) if err != nil { t.Fatal(err) } @@ -243,17 +243,17 @@ func TestMappingForPath(t *testing.T) { mapping := NewIndexMapping() mapping.AddDocumentMapping("a", docMappingA) - analyzerName := mapping.analyzerNameForPath("name") + analyzerName := mapping.AnalyzerNameForPath("name") if analyzerName != enFieldMapping.Analyzer { t.Errorf("expected '%s' got '%s'", enFieldMapping.Analyzer, analyzerName) } - analyzerName = mapping.analyzerNameForPath("nameCustom") + analyzerName = mapping.AnalyzerNameForPath("nameCustom") if analyzerName != customMapping.Analyzer { t.Errorf("expected '%s' got '%s'", customMapping.Analyzer, analyzerName) } - analyzerName = mapping.analyzerNameForPath("child.desc") + analyzerName = mapping.AnalyzerNameForPath("child.desc") if analyzerName != customFieldX.Analyzer { t.Errorf("expected '%s' got '%s'", customFieldX.Analyzer, analyzerName) } @@ -345,7 +345,7 @@ func TestEnablingDisablingStoringDynamicFields(t *testing.T) { } doc := document.NewDocument("x") mapping := NewIndexMapping() - err := mapping.mapDocument(doc, data) + err := mapping.MapDocument(doc, data) if err != nil { t.Fatal(err) } @@ -363,7 +363,7 @@ func TestEnablingDisablingStoringDynamicFields(t *testing.T) { mapping = NewIndexMapping() doc = document.NewDocument("y") - err = mapping.mapDocument(doc, data) + err = mapping.MapDocument(doc, data) if err != nil { t.Fatal(err) } @@ -377,7 +377,7 @@ func TestEnablingDisablingStoringDynamicFields(t *testing.T) { mapping = NewIndexMapping() mapping.StoreDynamic = true doc = document.NewDocument("y") - err = mapping.mapDocument(doc, data) + err = mapping.MapDocument(doc, data) if err != nil { t.Fatal(err) } @@ -405,7 +405,7 @@ func TestMappingBool(t *testing.T) { } doc := document.NewDocument("1") - err := mapping.mapDocument(doc, x) + err := mapping.MapDocument(doc, x) if err != nil { t.Fatal(err) } @@ -441,7 +441,7 @@ func TestDisableDefaultMapping(t *testing.T) { } doc := document.NewDocument("x") - err := indexMapping.mapDocument(doc, data) + err := indexMapping.MapDocument(doc, data) if err != nil { t.Error(err) } @@ -526,7 +526,7 @@ func TestInvalidIndexMappingStrict(t *testing.T) { mappingBytes := []byte(`{"typeField":"type","default_field":"all"}`) // first unmarhsal it without strict - var im IndexMapping + var im IndexMappingImpl err := json.Unmarshal(mappingBytes, &im) if err != nil { t.Fatal(err) @@ -590,7 +590,7 @@ func TestMappingBug353(t *testing.T) { mapping.DefaultMapping.AddSubDocumentMapping("Other", otherMapping) doc := document.NewDocument("x") - err = mapping.mapDocument(doc, data) + err = mapping.MapDocument(doc, data) if err != nil { t.Fatal(err) } @@ -636,7 +636,7 @@ func TestAnonymousStructFields(t *testing.T) { doc := document.NewDocument("1") m := NewIndexMapping() - err := m.mapDocument(doc, x) + err := m.MapDocument(doc, x) if err != nil { t.Fatal(err) } @@ -676,7 +676,7 @@ func TestAnonymousStructFields(t *testing.T) { } doc2 := document.NewDocument("2") - err = m.mapDocument(doc2, y) + err = m.MapDocument(doc2, y) if err != nil { t.Fatal(err) } @@ -712,7 +712,7 @@ func TestAnonymousStructFieldWithJSONStructTagEmptString(t *testing.T) { doc := document.NewDocument("1") m := NewIndexMapping() - err := m.mapDocument(doc, x) + err := m.MapDocument(doc, x) if err != nil { t.Fatal(err) } @@ -749,7 +749,7 @@ func TestMappingPrimitives(t *testing.T) { m := NewIndexMapping() for _, test := range tests { doc := document.NewDocument("x") - err := m.mapDocument(doc, test.data) + err := m.MapDocument(doc, test.data) if err != nil { t.Fatal(err) } diff --git a/reflect.go b/mapping/reflect.go similarity index 99% rename from reflect.go rename to mapping/reflect.go index 21fe397a..76451857 100644 --- a/reflect.go +++ b/mapping/reflect.go @@ -7,7 +7,7 @@ // either express or implied. See the License for the specific language governing permissions // and limitations under the License. -package bleve +package mapping import ( "reflect" diff --git a/query.go b/query.go index 595c7838..3af5f451 100644 --- a/query.go +++ b/query.go @@ -14,6 +14,7 @@ import ( "fmt" "github.com/blevesearch/bleve/index" + "github.com/blevesearch/bleve/mapping" "github.com/blevesearch/bleve/search" ) @@ -24,7 +25,7 @@ type Query interface { SetBoost(b float64) Query Field() string SetField(f string) Query - Searcher(i index.IndexReader, m *IndexMapping, explain bool) (search.Searcher, error) + Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) Validate() error } @@ -251,7 +252,7 @@ func ParseQuery(input []byte) (Query, error) { // expandQuery traverses the input query tree and returns a new tree where // query string queries have been expanded into base queries. Returned tree may // reference queries from the input tree or new queries. -func expandQuery(m *IndexMapping, query Query) (Query, error) { +func expandQuery(m mapping.IndexMapping, query Query) (Query, error) { var expand func(query Query) (Query, error) var expandSlice func(queries []Query) ([]Query, error) @@ -326,7 +327,7 @@ func expandQuery(m *IndexMapping, query Query) (Query, error) { // DumpQuery returns a string representation of the query tree, where query // string queries have been expanded into base queries. The output format is // meant for debugging purpose and may change in the future. -func DumpQuery(m *IndexMapping, query Query) (string, error) { +func DumpQuery(m mapping.IndexMapping, query Query) (string, error) { q, err := expandQuery(m, query) if err != nil { return "", err diff --git a/query_bool_field.go b/query_bool_field.go index ed3ac85f..16545994 100644 --- a/query_bool_field.go +++ b/query_bool_field.go @@ -11,6 +11,7 @@ package bleve import ( "github.com/blevesearch/bleve/index" + "github.com/blevesearch/bleve/mapping" "github.com/blevesearch/bleve/search" "github.com/blevesearch/bleve/search/searchers" ) @@ -47,10 +48,10 @@ func (q *boolFieldQuery) SetField(f string) Query { return q } -func (q *boolFieldQuery) Searcher(i index.IndexReader, m *IndexMapping, explain bool) (search.Searcher, error) { +func (q *boolFieldQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) { field := q.FieldVal if q.FieldVal == "" { - field = m.DefaultField + field = m.DefaultSearchField() } term := "F" if q.Bool { diff --git a/query_boolean.go b/query_boolean.go index 8dcb8efb..2fa2186e 100644 --- a/query_boolean.go +++ b/query_boolean.go @@ -14,6 +14,7 @@ import ( "fmt" "github.com/blevesearch/bleve/index" + "github.com/blevesearch/bleve/mapping" "github.com/blevesearch/bleve/search" "github.com/blevesearch/bleve/search/searchers" ) @@ -95,7 +96,7 @@ func (q *booleanQuery) SetBoost(b float64) Query { return q } -func (q *booleanQuery) Searcher(i index.IndexReader, m *IndexMapping, explain bool) (search.Searcher, error) { +func (q *booleanQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) { var err error var mustNotSearcher search.Searcher if q.MustNot != nil { diff --git a/query_conjunction.go b/query_conjunction.go index 99ad71c7..1c01e668 100644 --- a/query_conjunction.go +++ b/query_conjunction.go @@ -13,6 +13,7 @@ import ( "encoding/json" "github.com/blevesearch/bleve/index" + "github.com/blevesearch/bleve/mapping" "github.com/blevesearch/bleve/search" "github.com/blevesearch/bleve/search/searchers" ) @@ -45,7 +46,7 @@ func (q *conjunctionQuery) AddQuery(aq Query) *conjunctionQuery { return q } -func (q *conjunctionQuery) Searcher(i index.IndexReader, m *IndexMapping, explain bool) (search.Searcher, error) { +func (q *conjunctionQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) { ss := make([]search.Searcher, len(q.Conjuncts)) for in, conjunct := range q.Conjuncts { var err error diff --git a/query_date_range.go b/query_date_range.go index df0de333..7f84d3dc 100644 --- a/query_date_range.go +++ b/query_date_range.go @@ -14,6 +14,7 @@ import ( "math" "github.com/blevesearch/bleve/index" + "github.com/blevesearch/bleve/mapping" "github.com/blevesearch/bleve/numeric_util" "github.com/blevesearch/bleve/search" "github.com/blevesearch/bleve/search/searchers" @@ -71,7 +72,7 @@ func (q *dateRangeQuery) SetField(f string) Query { return q } -func (q *dateRangeQuery) Searcher(i index.IndexReader, m *IndexMapping, explain bool) (search.Searcher, error) { +func (q *dateRangeQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) { min, max, err := q.parseEndpoints() if err != nil { @@ -80,7 +81,7 @@ func (q *dateRangeQuery) Searcher(i index.IndexReader, m *IndexMapping, explain field := q.FieldVal if q.FieldVal == "" { - field = m.DefaultField + field = m.DefaultSearchField() } return searchers.NewNumericRangeSearcher(i, min, max, q.InclusiveStart, q.InclusiveEnd, field, q.BoostVal, explain) diff --git a/query_disjunction.go b/query_disjunction.go index 78e4bd92..be272ea3 100644 --- a/query_disjunction.go +++ b/query_disjunction.go @@ -13,6 +13,7 @@ import ( "encoding/json" "github.com/blevesearch/bleve/index" + "github.com/blevesearch/bleve/mapping" "github.com/blevesearch/bleve/search" "github.com/blevesearch/bleve/search/searchers" ) @@ -65,7 +66,7 @@ func (q *disjunctionQuery) SetMin(m float64) Query { return q } -func (q *disjunctionQuery) Searcher(i index.IndexReader, m *IndexMapping, explain bool) (search.Searcher, error) { +func (q *disjunctionQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) { ss := make([]search.Searcher, len(q.Disjuncts)) for in, disjunct := range q.Disjuncts { var err error diff --git a/query_docid.go b/query_docid.go index dce12bd4..5935eaa9 100644 --- a/query_docid.go +++ b/query_docid.go @@ -11,6 +11,7 @@ package bleve import ( "github.com/blevesearch/bleve/index" + "github.com/blevesearch/bleve/mapping" "github.com/blevesearch/bleve/search" "github.com/blevesearch/bleve/search/searchers" ) @@ -47,7 +48,7 @@ func (q *docIDQuery) SetField(f string) Query { return q } -func (q *docIDQuery) Searcher(i index.IndexReader, m *IndexMapping, explain bool) (search.Searcher, error) { +func (q *docIDQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) { return searchers.NewDocIDSearcher(i, q.IDs, q.BoostVal, explain) } diff --git a/query_fuzzy.go b/query_fuzzy.go index 2818035a..7644d643 100644 --- a/query_fuzzy.go +++ b/query_fuzzy.go @@ -11,6 +11,7 @@ package bleve import ( "github.com/blevesearch/bleve/index" + "github.com/blevesearch/bleve/mapping" "github.com/blevesearch/bleve/search" "github.com/blevesearch/bleve/search/searchers" ) @@ -75,10 +76,10 @@ func (q *fuzzyQuery) SetPrefix(p int) Query { return q } -func (q *fuzzyQuery) Searcher(i index.IndexReader, m *IndexMapping, explain bool) (search.Searcher, error) { +func (q *fuzzyQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) { field := q.FieldVal if q.FieldVal == "" { - field = m.DefaultField + field = m.DefaultSearchField() } return searchers.NewFuzzySearcher(i, q.Term, q.PrefixVal, q.FuzzinessVal, field, q.BoostVal, explain) } diff --git a/query_match.go b/query_match.go index 79ea3bcf..b13083a3 100644 --- a/query_match.go +++ b/query_match.go @@ -14,6 +14,7 @@ import ( "fmt" "github.com/blevesearch/bleve/index" + "github.com/blevesearch/bleve/mapping" "github.com/blevesearch/bleve/search" ) @@ -145,20 +146,20 @@ func (q *matchQuery) SetOperator(operator MatchQueryOperator) Query { return q } -func (q *matchQuery) Searcher(i index.IndexReader, m *IndexMapping, explain bool) (search.Searcher, error) { +func (q *matchQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) { field := q.FieldVal if q.FieldVal == "" { - field = m.DefaultField + field = m.DefaultSearchField() } analyzerName := "" if q.Analyzer != "" { analyzerName = q.Analyzer } else { - analyzerName = m.analyzerNameForPath(field) + analyzerName = m.AnalyzerNameForPath(field) } - analyzer := m.analyzerNamed(analyzerName) + analyzer := m.AnalyzerNamed(analyzerName) if analyzer == nil { return nil, fmt.Errorf("no analyzer named '%s' registered", q.Analyzer) diff --git a/query_match_all.go b/query_match_all.go index 02232bcd..2ae2acb3 100644 --- a/query_match_all.go +++ b/query_match_all.go @@ -13,6 +13,7 @@ import ( "encoding/json" "github.com/blevesearch/bleve/index" + "github.com/blevesearch/bleve/mapping" "github.com/blevesearch/bleve/search" "github.com/blevesearch/bleve/search/searchers" ) @@ -38,7 +39,7 @@ func (q *matchAllQuery) SetBoost(b float64) Query { return q } -func (q *matchAllQuery) Searcher(i index.IndexReader, m *IndexMapping, explain bool) (search.Searcher, error) { +func (q *matchAllQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) { return searchers.NewMatchAllSearcher(i, q.BoostVal, explain) } diff --git a/query_match_none.go b/query_match_none.go index b13ca6c8..14fddab5 100644 --- a/query_match_none.go +++ b/query_match_none.go @@ -13,6 +13,7 @@ import ( "encoding/json" "github.com/blevesearch/bleve/index" + "github.com/blevesearch/bleve/mapping" "github.com/blevesearch/bleve/search" "github.com/blevesearch/bleve/search/searchers" ) @@ -38,7 +39,7 @@ func (q *matchNoneQuery) SetBoost(b float64) Query { return q } -func (q *matchNoneQuery) Searcher(i index.IndexReader, m *IndexMapping, explain bool) (search.Searcher, error) { +func (q *matchNoneQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) { return searchers.NewMatchNoneSearcher(i) } diff --git a/query_match_phrase.go b/query_match_phrase.go index 8deed182..1d588628 100644 --- a/query_match_phrase.go +++ b/query_match_phrase.go @@ -14,6 +14,7 @@ import ( "github.com/blevesearch/bleve/analysis" "github.com/blevesearch/bleve/index" + "github.com/blevesearch/bleve/mapping" "github.com/blevesearch/bleve/search" ) @@ -57,19 +58,19 @@ func (q *matchPhraseQuery) SetField(f string) Query { return q } -func (q *matchPhraseQuery) Searcher(i index.IndexReader, m *IndexMapping, explain bool) (search.Searcher, error) { +func (q *matchPhraseQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) { field := q.FieldVal if q.FieldVal == "" { - field = m.DefaultField + field = m.DefaultSearchField() } analyzerName := "" if q.Analyzer != "" { analyzerName = q.Analyzer } else { - analyzerName = m.analyzerNameForPath(field) + analyzerName = m.AnalyzerNameForPath(field) } - analyzer := m.analyzerNamed(analyzerName) + analyzer := m.AnalyzerNamed(analyzerName) if analyzer == nil { return nil, fmt.Errorf("no analyzer named '%s' registered", q.Analyzer) } diff --git a/query_numeric_range.go b/query_numeric_range.go index 87d5f348..973b9cb3 100644 --- a/query_numeric_range.go +++ b/query_numeric_range.go @@ -11,6 +11,7 @@ package bleve import ( "github.com/blevesearch/bleve/index" + "github.com/blevesearch/bleve/mapping" "github.com/blevesearch/bleve/search" "github.com/blevesearch/bleve/search/searchers" ) @@ -65,10 +66,10 @@ func (q *numericRangeQuery) SetField(f string) Query { return q } -func (q *numericRangeQuery) Searcher(i index.IndexReader, m *IndexMapping, explain bool) (search.Searcher, error) { +func (q *numericRangeQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) { field := q.FieldVal if q.FieldVal == "" { - field = m.DefaultField + field = m.DefaultSearchField() } return searchers.NewNumericRangeSearcher(i, q.Min, q.Max, q.InclusiveMin, q.InclusiveMax, field, q.BoostVal, explain) } diff --git a/query_phrase.go b/query_phrase.go index bfc2e245..9f8df326 100644 --- a/query_phrase.go +++ b/query_phrase.go @@ -13,6 +13,7 @@ import ( "encoding/json" "github.com/blevesearch/bleve/index" + "github.com/blevesearch/bleve/mapping" "github.com/blevesearch/bleve/search" "github.com/blevesearch/bleve/search/searchers" ) @@ -54,7 +55,7 @@ func (q *phraseQuery) SetBoost(b float64) Query { return q } -func (q *phraseQuery) Searcher(i index.IndexReader, m *IndexMapping, explain bool) (search.Searcher, error) { +func (q *phraseQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) { conjunctionQuery := NewConjunctionQuery(q.termQueries) conjunctionSearcher, err := conjunctionQuery.Searcher(i, m, explain) diff --git a/query_prefix.go b/query_prefix.go index 8d032e54..a3710a1c 100644 --- a/query_prefix.go +++ b/query_prefix.go @@ -11,6 +11,7 @@ package bleve import ( "github.com/blevesearch/bleve/index" + "github.com/blevesearch/bleve/mapping" "github.com/blevesearch/bleve/search" "github.com/blevesearch/bleve/search/searchers" ) @@ -49,10 +50,10 @@ func (q *prefixQuery) SetField(f string) Query { return q } -func (q *prefixQuery) Searcher(i index.IndexReader, m *IndexMapping, explain bool) (search.Searcher, error) { +func (q *prefixQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) { field := q.FieldVal if q.FieldVal == "" { - field = m.DefaultField + field = m.DefaultSearchField() } return searchers.NewTermPrefixSearcher(i, q.Prefix, field, q.BoostVal, explain) } diff --git a/query_regexp.go b/query_regexp.go index 06144c12..89e0e7c4 100644 --- a/query_regexp.go +++ b/query_regexp.go @@ -14,6 +14,7 @@ import ( "strings" "github.com/blevesearch/bleve/index" + "github.com/blevesearch/bleve/mapping" "github.com/blevesearch/bleve/search" "github.com/blevesearch/bleve/search/searchers" ) @@ -53,10 +54,10 @@ func (q *regexpQuery) SetField(f string) Query { return q } -func (q *regexpQuery) Searcher(i index.IndexReader, m *IndexMapping, explain bool) (search.Searcher, error) { +func (q *regexpQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) { field := q.FieldVal if q.FieldVal == "" { - field = m.DefaultField + field = m.DefaultSearchField() } err := q.compile() if err != nil { diff --git a/query_string.go b/query_string.go index 005191cd..eed878b5 100644 --- a/query_string.go +++ b/query_string.go @@ -11,6 +11,7 @@ package bleve import ( "github.com/blevesearch/bleve/index" + "github.com/blevesearch/bleve/mapping" "github.com/blevesearch/bleve/search" ) @@ -38,7 +39,7 @@ func (q *queryStringQuery) SetBoost(b float64) Query { return q } -func (q *queryStringQuery) Searcher(i index.IndexReader, m *IndexMapping, explain bool) (search.Searcher, error) { +func (q *queryStringQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) { newQuery, err := parseQuerySyntax(q.Query) if err != nil { return nil, err diff --git a/query_string_parser_test.go b/query_string_parser_test.go index cef9be3b..68a4b27d 100644 --- a/query_string_parser_test.go +++ b/query_string_parser_test.go @@ -13,6 +13,8 @@ import ( "reflect" "strings" "testing" + + "github.com/blevesearch/bleve/mapping" ) func TestQuerySyntaxParserValid(t *testing.T) { @@ -23,7 +25,7 @@ func TestQuerySyntaxParserValid(t *testing.T) { tests := []struct { input string result Query - mapping *IndexMapping + mapping mapping.IndexMapping }{ { input: "test", diff --git a/query_term.go b/query_term.go index df92b454..683cdf1e 100644 --- a/query_term.go +++ b/query_term.go @@ -11,6 +11,7 @@ package bleve import ( "github.com/blevesearch/bleve/index" + "github.com/blevesearch/bleve/mapping" "github.com/blevesearch/bleve/search" "github.com/blevesearch/bleve/search/searchers" ) @@ -48,10 +49,10 @@ func (q *termQuery) SetField(f string) Query { return q } -func (q *termQuery) Searcher(i index.IndexReader, m *IndexMapping, explain bool) (search.Searcher, error) { +func (q *termQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) { field := q.FieldVal if q.FieldVal == "" { - field = m.DefaultField + field = m.DefaultSearchField() } return searchers.NewTermSearcher(i, q.Term, field, q.BoostVal, explain) } diff --git a/query_test.go b/query_test.go index 5cd4f3ea..e7b39876 100644 --- a/query_test.go +++ b/query_test.go @@ -268,7 +268,7 @@ func TestQueryValidate(t *testing.T) { } func TestDumpQuery(t *testing.T) { - mapping := &IndexMapping{} + mapping := NewIndexMapping() q := NewQueryStringQuery("+water -light beer") s, err := DumpQuery(mapping, q) if err != nil { diff --git a/query_wildcard.go b/query_wildcard.go index 32fd3433..7b713454 100644 --- a/query_wildcard.go +++ b/query_wildcard.go @@ -14,6 +14,7 @@ import ( "strings" "github.com/blevesearch/bleve/index" + "github.com/blevesearch/bleve/mapping" "github.com/blevesearch/bleve/search" "github.com/blevesearch/bleve/search/searchers" ) @@ -74,10 +75,10 @@ func (q *wildcardQuery) SetField(f string) Query { return q } -func (q *wildcardQuery) Searcher(i index.IndexReader, m *IndexMapping, explain bool) (search.Searcher, error) { +func (q *wildcardQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, explain bool) (search.Searcher, error) { field := q.FieldVal if q.FieldVal == "" { - field = m.DefaultField + field = m.DefaultSearchField() } if q.compiled == nil { var err error diff --git a/test/integration_test.go b/test/integration_test.go index ad280e27..3cb03da2 100644 --- a/test/integration_test.go +++ b/test/integration_test.go @@ -24,6 +24,7 @@ import ( // we must explicitly include any functionality we plan on testing _ "github.com/blevesearch/bleve/analysis/analyzers/keyword_analyzer" + "github.com/blevesearch/bleve/mapping" // allow choosing alternate kvstores _ "github.com/blevesearch/bleve/config" @@ -77,7 +78,7 @@ func runTestDir(t *testing.T, dir, datasetName string) { t.Errorf("error reading mapping: %v", err) return } - var mapping bleve.IndexMapping + var mapping mapping.IndexMappingImpl err = json.Unmarshal(mappingBytes, &mapping) if err != nil { t.Errorf("error unmarshalling mapping: %v", err)