1// Copyright (c) 2014 Couchbase, Inc. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package bleve 16 17import ( 18 "github.com/blevesearch/bleve/document" 19 "github.com/blevesearch/bleve/index" 20 "github.com/blevesearch/bleve/index/store" 21 "github.com/blevesearch/bleve/mapping" 22 "golang.org/x/net/context" 23) 24 25// A Batch groups together multiple Index and Delete 26// operations you would like performed at the same 27// time. The Batch structure is NOT thread-safe. 28// You should only perform operations on a batch 29// from a single thread at a time. Once batch 30// execution has started, you may not modify it. 31type Batch struct { 32 index Index 33 internal *index.Batch 34} 35 36// Index adds the specified index operation to the 37// batch. NOTE: the bleve Index is not updated 38// until the batch is executed. 39func (b *Batch) Index(id string, data interface{}) error { 40 if id == "" { 41 return ErrorEmptyID 42 } 43 doc := document.NewDocument(id) 44 err := b.index.Mapping().MapDocument(doc, data) 45 if err != nil { 46 return err 47 } 48 b.internal.Update(doc) 49 return nil 50} 51 52// IndexAdvanced adds the specified index operation to the 53// batch which skips the mapping. NOTE: the bleve Index is not updated 54// until the batch is executed. 55func (b *Batch) IndexAdvanced(doc *document.Document) (err error) { 56 if doc.ID == "" { 57 return ErrorEmptyID 58 } 59 b.internal.Update(doc) 60 return nil 61} 62 63// Delete adds the specified delete operation to the 64// batch. NOTE: the bleve Index is not updated until 65// the batch is executed. 66func (b *Batch) Delete(id string) { 67 if id != "" { 68 b.internal.Delete(id) 69 } 70} 71 72// SetInternal adds the specified set internal 73// operation to the batch. NOTE: the bleve Index is 74// not updated until the batch is executed. 75func (b *Batch) SetInternal(key, val []byte) { 76 b.internal.SetInternal(key, val) 77} 78 79// DeleteInternal adds the specified delete internal 80// operation to the batch. NOTE: the bleve Index is 81// not updated until the batch is executed. 82func (b *Batch) DeleteInternal(key []byte) { 83 b.internal.DeleteInternal(key) 84} 85 86// Size returns the total number of operations inside the batch 87// including normal index operations and internal operations. 88func (b *Batch) Size() int { 89 return len(b.internal.IndexOps) + len(b.internal.InternalOps) 90} 91 92// String prints a user friendly string representation of what 93// is inside this batch. 94func (b *Batch) String() string { 95 return b.internal.String() 96} 97 98// Reset returns a Batch to the empty state so that it can 99// be re-used in the future. 100func (b *Batch) Reset() { 101 b.internal.Reset() 102} 103 104// An Index implements all the indexing and searching 105// capabilities of bleve. An Index can be created 106// using the New() and Open() methods. 107// 108// Index() takes an input value, deduces a DocumentMapping for its type, 109// assigns string paths to its fields or values then applies field mappings on 110// them. 111// 112// The DocumentMapping used to index a value is deduced by the following rules: 113// 1) If value implements mapping.bleveClassifier interface, resolve the mapping 114// from BleveType(). 115// 2) If value implements mapping.Classifier interface, resolve the mapping 116// from Type(). 117// 3) If value has a string field or value at IndexMapping.TypeField. 118// (defaulting to "_type"), use it to resolve the mapping. Fields addressing 119// is described below. 120// 4) If IndexMapping.DefaultType is registered, return it. 121// 5) Return IndexMapping.DefaultMapping. 122// 123// Each field or nested field of the value is identified by a string path, then 124// mapped to one or several FieldMappings which extract the result for analysis. 125// 126// Struct values fields are identified by their "json:" tag, or by their name. 127// Nested fields are identified by prefixing with their parent identifier, 128// separated by a dot. 129// 130// Map values entries are identified by their string key. Entries not indexed 131// by strings are ignored. Entry values are identified recursively like struct 132// fields. 133// 134// Slice and array values are identified by their field name. Their elements 135// are processed sequentially with the same FieldMapping. 136// 137// String, float64 and time.Time values are identified by their field name. 138// Other types are ignored. 139// 140// Each value identifier is decomposed in its parts and recursively address 141// SubDocumentMappings in the tree starting at the root DocumentMapping. If a 142// mapping is found, all its FieldMappings are applied to the value. If no 143// mapping is found and the root DocumentMapping is dynamic, default mappings 144// are used based on value type and IndexMapping default configurations. 145// 146// Finally, mapped values are analyzed, indexed or stored. See 147// FieldMapping.Analyzer to know how an analyzer is resolved for a given field. 148// 149// Examples: 150// 151// type Date struct { 152// Day string `json:"day"` 153// Month string 154// Year string 155// } 156// 157// type Person struct { 158// FirstName string `json:"first_name"` 159// LastName string 160// BirthDate Date `json:"birth_date"` 161// } 162// 163// A Person value FirstName is mapped by the SubDocumentMapping at 164// "first_name". Its LastName is mapped by the one at "LastName". The day of 165// BirthDate is mapped to the SubDocumentMapping "day" of the root 166// SubDocumentMapping "birth_date". It will appear as the "birth_date.day" 167// field in the index. The month is mapped to "birth_date.Month". 168type Index interface { 169 // Index analyzes, indexes or stores mapped data fields. Supplied 170 // identifier is bound to analyzed data and will be retrieved by search 171 // requests. See Index interface documentation for details about mapping 172 // rules. 173 Index(id string, data interface{}) error 174 Delete(id string) error 175 176 NewBatch() *Batch 177 Batch(b *Batch) error 178 179 // Document returns specified document or nil if the document is not 180 // indexed or stored. 181 Document(id string) (*document.Document, error) 182 // DocCount returns the number of documents in the index. 183 DocCount() (uint64, error) 184 185 Search(req *SearchRequest) (*SearchResult, error) 186 SearchInContext(ctx context.Context, req *SearchRequest) (*SearchResult, error) 187 188 Fields() ([]string, error) 189 190 FieldDict(field string) (index.FieldDict, error) 191 FieldDictRange(field string, startTerm []byte, endTerm []byte) (index.FieldDict, error) 192 FieldDictPrefix(field string, termPrefix []byte) (index.FieldDict, error) 193 194 Close() error 195 196 Mapping() mapping.IndexMapping 197 198 Stats() *IndexStat 199 StatsMap() map[string]interface{} 200 201 GetInternal(key []byte) ([]byte, error) 202 SetInternal(key, val []byte) error 203 DeleteInternal(key []byte) error 204 205 // Name returns the name of the index (by default this is the path) 206 Name() string 207 // SetName lets you assign your own logical name to this index 208 SetName(string) 209 210 // Advanced returns the indexer and data store, exposing lower level 211 // methods to enumerate records and access data. 212 Advanced() (index.Index, store.KVStore, error) 213} 214 215// New index at the specified path, must not exist. 216// The provided mapping will be used for all 217// Index/Search operations. 218func New(path string, mapping mapping.IndexMapping) (Index, error) { 219 return newIndexUsing(path, mapping, Config.DefaultIndexType, Config.DefaultKVStore, nil) 220} 221 222// NewMemOnly creates a memory-only index. 223// The contents of the index is NOT persisted, 224// and will be lost once closed. 225// The provided mapping will be used for all 226// Index/Search operations. 227func NewMemOnly(mapping mapping.IndexMapping) (Index, error) { 228 return newIndexUsing("", mapping, Config.DefaultIndexType, Config.DefaultMemKVStore, nil) 229} 230 231// NewUsing creates index at the specified path, 232// which must not already exist. 233// The provided mapping will be used for all 234// Index/Search operations. 235// The specified index type will be used. 236// The specified kvstore implementation will be used 237// and the provided kvconfig will be passed to its 238// constructor. Note that currently the values of kvconfig must 239// be able to be marshaled and unmarshaled using the encoding/json library (used 240// when reading/writing the index metadata file). 241func NewUsing(path string, mapping mapping.IndexMapping, indexType string, kvstore string, kvconfig map[string]interface{}) (Index, error) { 242 return newIndexUsing(path, mapping, indexType, kvstore, kvconfig) 243} 244 245// Open index at the specified path, must exist. 246// The mapping used when it was created will be used for all Index/Search operations. 247func Open(path string) (Index, error) { 248 return openIndexUsing(path, nil) 249} 250 251// OpenUsing opens index at the specified path, must exist. 252// The mapping used when it was created will be used for all Index/Search operations. 253// The provided runtimeConfig can override settings 254// persisted when the kvstore was created. 255func OpenUsing(path string, runtimeConfig map[string]interface{}) (Index, error) { 256 return openIndexUsing(path, runtimeConfig) 257} 258