0
0
Fork 0

refactored field from struct to interface

This commit is contained in:
Marty Schoch 2014-07-14 14:47:05 -04:00
parent f225d484b3
commit d3466f3919
8 changed files with 73 additions and 53 deletions

View File

@ -13,18 +13,18 @@ import (
)
type Document struct {
ID string `json:"id"`
Fields []*Field `json:"fields"`
ID string `json:"id"`
Fields []Field `json:"fields"`
}
func NewDocument(id string) *Document {
return &Document{
ID: id,
Fields: make([]*Field, 0),
Fields: make([]Field, 0),
}
}
func (d *Document) AddField(f *Field) *Document {
func (d *Document) AddField(f Field) *Document {
d.Fields = append(d.Fields, f)
return d
}

View File

@ -12,18 +12,9 @@ import (
"github.com/couchbaselabs/bleve/analysis"
)
type Field struct {
Name string
Options IndexingOptions
Analyzer *analysis.Analyzer
Value []byte
}
func NewField(name string, value []byte, options IndexingOptions, analyzer *analysis.Analyzer) *Field {
return &Field{
Name: name,
Options: options,
Analyzer: analyzer,
Value: value,
}
type Field interface {
Name() string
Options() IndexingOptions
Analyzer() *analysis.Analyzer
Value() []byte
}

View File

@ -27,15 +27,47 @@ func init() {
const DEFAULT_TEXT_INDEXING_OPTIONS = INDEX_FIELD
func NewTextField(name string, value []byte) *Field {
type TextField struct {
name string
options IndexingOptions
analyzer *analysis.Analyzer
value []byte
}
func (t *TextField) Name() string {
return t.name
}
func (t *TextField) Options() IndexingOptions {
return t.options
}
func (t *TextField) Analyzer() *analysis.Analyzer {
return t.analyzer
}
func (t *TextField) Value() []byte {
return t.value
}
func NewTextField(name string, value []byte) *TextField {
return NewTextFieldWithIndexingOptions(name, value, DEFAULT_TEXT_INDEXING_OPTIONS)
}
func NewTextFieldWithIndexingOptions(name string, value []byte, options IndexingOptions) *Field {
return &Field{
Name: name,
Options: options,
Analyzer: standardAnalyzer,
Value: value,
func NewTextFieldWithIndexingOptions(name string, value []byte, options IndexingOptions) *TextField {
return &TextField{
name: name,
options: options,
analyzer: standardAnalyzer,
value: value,
}
}
func NewTextFieldCustom(name string, value []byte, options IndexingOptions, analyzer *analysis.Analyzer) *TextField {
return &TextField{
name: name,
options: options,
analyzer: analyzer,
value: value,
}
}

View File

@ -265,29 +265,29 @@ func (udc *UpsideDownCouch) Update(doc *document.Document) error {
backIndexStoredFields := make([]uint16, 0)
for _, field := range doc.Fields {
fieldIndex, fieldExists := udc.fieldIndexes[field.Name]
fieldIndex, fieldExists := udc.fieldIndexes[field.Name()]
if !fieldExists {
// assign next field id
fieldIndex = uint16(udc.lastFieldIndex + 1)
udc.fieldIndexes[field.Name] = fieldIndex
udc.fieldIndexes[field.Name()] = fieldIndex
// ensure this batch adds a row for this field
row := NewFieldRow(uint16(fieldIndex), field.Name)
row := NewFieldRow(uint16(fieldIndex), field.Name())
updateRows = append(updateRows, row)
udc.lastFieldIndex = int(fieldIndex)
}
existingTermMap, fieldExistedInDoc := existingTermFieldMaps[int(fieldIndex)]
if field.Options.IsIndexed() {
if field.Options().IsIndexed() {
analyzer := field.Analyzer
tokens := analyzer.Analyze(field.Value)
analyzer := field.Analyzer()
tokens := analyzer.Analyze(field.Value())
fieldLength := len(tokens) // number of tokens in this doc field
fieldNorm := float32(1.0 / math.Sqrt(float64(fieldLength)))
tokenFreqs := analysis.TokenFrequency(tokens)
for _, tf := range tokenFreqs {
var termFreqRow *TermFrequencyRow
if field.Options.IncludeTermVectors() {
if field.Options().IncludeTermVectors() {
tv := termVectorsFromTokenFreq(uint16(fieldIndex), tf)
termFreqRow = NewTermFrequencyRowWithTermVectors(tf.Term, uint16(fieldIndex), doc.ID, uint64(frequencyFromTokenFreq(tf)), fieldNorm, tv)
} else {
@ -318,8 +318,8 @@ func (udc *UpsideDownCouch) Update(doc *document.Document) error {
}
}
if field.Options.IsStored() {
storedRow := NewStoredRow(doc.ID, uint16(fieldIndex), field.Value)
if field.Options().IsStored() {
storedRow := NewStoredRow(doc.ID, uint16(fieldIndex), field.Value())
backIndexStoredFields = append(backIndexStoredFields, fieldIndex)
_, ok := existingStoredFieldMap[uint16(fieldIndex)]
if ok {
@ -502,10 +502,7 @@ func (udc *UpsideDownCouch) Document(id string) (*document.Document, error) {
return nil, err
}
if row != nil {
rv.AddField(&document.Field{
Name: udc.fieldIndexToName(row.field),
Value: row.Value(),
})
rv.AddField(document.NewTextField(udc.fieldIndexToName(row.field), row.Value()))
}
it.Next()

View File

@ -312,7 +312,7 @@ func TestIndexInsertWithStore(t *testing.T) {
if len(storedDoc.Fields) != 1 {
t.Errorf("expected 1 stored field, got %d", len(storedDoc.Fields))
}
if string(storedDoc.Fields[0].Value) != "test" {
t.Errorf("expected field content 'test', got '%s'", string(storedDoc.Fields[0].Value))
if string(storedDoc.Fields[0].Value()) != "test" {
t.Errorf("expected field content 'test', got '%s'", string(storedDoc.Fields[0].Value()))
}
}

View File

@ -63,8 +63,8 @@ func (s *SimpleHighlighter) BestFragmentsInField(dm *DocumentMatch, doc *documen
fq := make(FragmentQueue, 0)
heap.Init(&fq)
for _, f := range doc.Fields {
if f.Name == field {
fieldData := f.Value
if f.Name() == field {
fieldData := f.Value()
fragments := s.fragmenter.Fragment(fieldData, orderedTermLocations)
for _, fragment := range fragments {
scorer.Score(fragment)

View File

@ -30,61 +30,61 @@ func TestTermSearcher(t *testing.T) {
i := upside_down.NewUpsideDownCouch(inMemStore)
i.Update(&document.Document{
ID: "a",
Fields: []*document.Field{
Fields: []document.Field{
document.NewTextField("desc", []byte("beer")),
},
})
i.Update(&document.Document{
ID: "b",
Fields: []*document.Field{
Fields: []document.Field{
document.NewTextField("desc", []byte("beer")),
},
})
i.Update(&document.Document{
ID: "c",
Fields: []*document.Field{
Fields: []document.Field{
document.NewTextField("desc", []byte("beer")),
},
})
i.Update(&document.Document{
ID: "d",
Fields: []*document.Field{
Fields: []document.Field{
document.NewTextField("desc", []byte("beer")),
},
})
i.Update(&document.Document{
ID: "e",
Fields: []*document.Field{
Fields: []document.Field{
document.NewTextField("desc", []byte("beer")),
},
})
i.Update(&document.Document{
ID: "f",
Fields: []*document.Field{
Fields: []document.Field{
document.NewTextField("desc", []byte("beer")),
},
})
i.Update(&document.Document{
ID: "g",
Fields: []*document.Field{
Fields: []document.Field{
document.NewTextField("desc", []byte("beer")),
},
})
i.Update(&document.Document{
ID: "h",
Fields: []*document.Field{
Fields: []document.Field{
document.NewTextField("desc", []byte("beer")),
},
})
i.Update(&document.Document{
ID: "i",
Fields: []*document.Field{
Fields: []document.Field{
document.NewTextField("desc", []byte("beer")),
},
})
i.Update(&document.Document{
ID: "j",
Fields: []*document.Field{
Fields: []document.Field{
document.NewTextField("title", []byte("cat")),
},
})

View File

@ -67,7 +67,7 @@ func (s *JsonPointerShredder) Shred(id string, body []byte) (*document.Document,
analyzer, custom := s.analyzers[fieldName]
if custom {
options := s.options[fieldName]
field := document.NewField(fieldName, fieldValue, options, analyzer)
field := document.NewTextFieldCustom(fieldName, fieldValue, options, analyzer)
rv.AddField(field)
} else {
field := document.NewTextField(fieldName, fieldValue)