fixed bug with internal get/set/delete, added tests
This commit is contained in:
parent
6b7c12b8bd
commit
4d53db9fc8
|
@ -506,27 +506,6 @@ func (udc *UpsideDownCouch) backIndexRowsForBatch(batch index.Batch) (map[string
|
|||
return rv, nil
|
||||
}
|
||||
|
||||
func (udc *UpsideDownCouch) Dump() {
|
||||
it := udc.store.Iterator([]byte{0})
|
||||
defer it.Close()
|
||||
key, val, valid := it.Current()
|
||||
for valid {
|
||||
|
||||
row, err := ParseFromKeyValue(key, val)
|
||||
if err != nil {
|
||||
fmt.Printf("error parsing key/value: %v", err)
|
||||
return
|
||||
}
|
||||
if row != nil {
|
||||
fmt.Printf("%v\n", row)
|
||||
fmt.Printf("Key: % -100x\nValue: % -100x\n\n", key, val)
|
||||
}
|
||||
|
||||
it.Next()
|
||||
key, val, valid = it.Current()
|
||||
}
|
||||
}
|
||||
|
||||
func (udc *UpsideDownCouch) Fields() ([]string, error) {
|
||||
rv := make([]string, 0)
|
||||
it := udc.store.Iterator([]byte{'f'})
|
||||
|
@ -553,71 +532,6 @@ func (udc *UpsideDownCouch) Fields() ([]string, error) {
|
|||
return rv, nil
|
||||
}
|
||||
|
||||
func (udc *UpsideDownCouch) DumpFields() {
|
||||
it := udc.store.Iterator([]byte{'f'})
|
||||
defer it.Close()
|
||||
key, val, valid := it.Current()
|
||||
for valid {
|
||||
if !bytes.HasPrefix(key, []byte{'f'}) {
|
||||
break
|
||||
}
|
||||
|
||||
row, err := ParseFromKeyValue(key, val)
|
||||
if err != nil {
|
||||
fmt.Printf("error parsing key/value: %v", err)
|
||||
return
|
||||
}
|
||||
if row != nil {
|
||||
fmt.Printf("%v\n", row)
|
||||
fmt.Printf("Key: % -100x\nValue: % -100x\n\n", key, val)
|
||||
}
|
||||
|
||||
it.Next()
|
||||
key, val, valid = it.Current()
|
||||
}
|
||||
}
|
||||
|
||||
type keyset [][]byte
|
||||
|
||||
func (k keyset) Len() int { return len(k) }
|
||||
func (k keyset) Swap(i, j int) { k[i], k[j] = k[j], k[i] }
|
||||
func (k keyset) Less(i, j int) bool { return bytes.Compare(k[i], k[j]) < 0 }
|
||||
|
||||
// DumpDoc returns all rows in the index related to this doc id
|
||||
func (udc *UpsideDownCouch) DumpDoc(id string) ([]interface{}, error) {
|
||||
rv := make([]interface{}, 0)
|
||||
back, err := udc.backIndexRowForDoc(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
keys := make(keyset, 0)
|
||||
for _, stored := range back.storedFields {
|
||||
sr := NewStoredRow(id, stored, 'x', []byte{})
|
||||
key := sr.Key()
|
||||
keys = append(keys, key)
|
||||
}
|
||||
for _, entry := range back.entries {
|
||||
tfr := NewTermFrequencyRow(entry.term, entry.field, id, 0, 0)
|
||||
key := tfr.Key()
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Sort(keys)
|
||||
|
||||
for _, key := range keys {
|
||||
value, err := udc.store.Get(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
row, err := ParseFromKeyValue(key, value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rv = append(rv, row)
|
||||
}
|
||||
|
||||
return rv, nil
|
||||
}
|
||||
|
||||
func (udc *UpsideDownCouch) TermFieldReader(term []byte, fieldName string) (index.TermFieldReader, error) {
|
||||
fieldIndex, fieldExists := udc.fieldIndexes[fieldName]
|
||||
if fieldExists {
|
||||
|
@ -793,17 +707,97 @@ func (udc *UpsideDownCouch) SetInternal(key, val []byte) error {
|
|||
}
|
||||
|
||||
func (udc *UpsideDownCouch) GetInternal(key []byte) ([]byte, error) {
|
||||
internalRow, err := NewInternalRowKV(key, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
internalRow := NewInternalRow(key, nil)
|
||||
return udc.store.Get(internalRow.Key())
|
||||
}
|
||||
|
||||
func (udc *UpsideDownCouch) DeleteInternal(key []byte) error {
|
||||
internalRow, err := NewInternalRowKV(key, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
internalRow := NewInternalRow(key, nil)
|
||||
return udc.store.Delete(internalRow.Key())
|
||||
}
|
||||
|
||||
func (udc *UpsideDownCouch) Dump() {
|
||||
it := udc.store.Iterator([]byte{0})
|
||||
defer it.Close()
|
||||
key, val, valid := it.Current()
|
||||
for valid {
|
||||
|
||||
row, err := ParseFromKeyValue(key, val)
|
||||
if err != nil {
|
||||
fmt.Printf("error parsing key/value: %v", err)
|
||||
return
|
||||
}
|
||||
if row != nil {
|
||||
fmt.Printf("%v\n", row)
|
||||
fmt.Printf("Key: % -100x\nValue: % -100x\n\n", key, val)
|
||||
}
|
||||
|
||||
it.Next()
|
||||
key, val, valid = it.Current()
|
||||
}
|
||||
}
|
||||
|
||||
func (udc *UpsideDownCouch) DumpFields() {
|
||||
it := udc.store.Iterator([]byte{'f'})
|
||||
defer it.Close()
|
||||
key, val, valid := it.Current()
|
||||
for valid {
|
||||
if !bytes.HasPrefix(key, []byte{'f'}) {
|
||||
break
|
||||
}
|
||||
|
||||
row, err := ParseFromKeyValue(key, val)
|
||||
if err != nil {
|
||||
fmt.Printf("error parsing key/value: %v", err)
|
||||
return
|
||||
}
|
||||
if row != nil {
|
||||
fmt.Printf("%v\n", row)
|
||||
fmt.Printf("Key: % -100x\nValue: % -100x\n\n", key, val)
|
||||
}
|
||||
|
||||
it.Next()
|
||||
key, val, valid = it.Current()
|
||||
}
|
||||
}
|
||||
|
||||
type keyset [][]byte
|
||||
|
||||
func (k keyset) Len() int { return len(k) }
|
||||
func (k keyset) Swap(i, j int) { k[i], k[j] = k[j], k[i] }
|
||||
func (k keyset) Less(i, j int) bool { return bytes.Compare(k[i], k[j]) < 0 }
|
||||
|
||||
// DumpDoc returns all rows in the index related to this doc id
|
||||
func (udc *UpsideDownCouch) DumpDoc(id string) ([]interface{}, error) {
|
||||
rv := make([]interface{}, 0)
|
||||
back, err := udc.backIndexRowForDoc(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
keys := make(keyset, 0)
|
||||
for _, stored := range back.storedFields {
|
||||
sr := NewStoredRow(id, stored, 'x', []byte{})
|
||||
key := sr.Key()
|
||||
keys = append(keys, key)
|
||||
}
|
||||
for _, entry := range back.entries {
|
||||
tfr := NewTermFrequencyRow(entry.term, entry.field, id, 0, 0)
|
||||
key := tfr.Key()
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Sort(keys)
|
||||
|
||||
for _, key := range keys {
|
||||
value, err := udc.store.Get(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
row, err := ParseFromKeyValue(key, value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rv = append(rv, row)
|
||||
}
|
||||
|
||||
return rv, nil
|
||||
}
|
||||
|
|
|
@ -10,13 +10,16 @@ package upside_down
|
|||
|
||||
import (
|
||||
"os"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/couchbaselabs/bleve/analysis"
|
||||
"github.com/couchbaselabs/bleve/analysis/tokenizers/regexp_tokenizer"
|
||||
"github.com/couchbaselabs/bleve/document"
|
||||
"github.com/couchbaselabs/bleve/index/store/gouchstore"
|
||||
"github.com/couchbaselabs/bleve/index"
|
||||
"github.com/couchbaselabs/bleve/index/store/leveldb"
|
||||
)
|
||||
|
||||
var testAnalyzer = &analysis.Analyzer{
|
||||
|
@ -26,7 +29,7 @@ var testAnalyzer = &analysis.Analyzer{
|
|||
func TestIndexOpenReopen(t *testing.T) {
|
||||
defer os.RemoveAll("test")
|
||||
|
||||
store, err := gouchstore.Open("test")
|
||||
store, err := leveldb.Open("test", true)
|
||||
idx := NewUpsideDownCouch(store)
|
||||
err = idx.Open()
|
||||
if err != nil {
|
||||
|
@ -49,7 +52,7 @@ func TestIndexOpenReopen(t *testing.T) {
|
|||
// now close it
|
||||
idx.Close()
|
||||
|
||||
store, err = gouchstore.Open("test")
|
||||
store, err = leveldb.Open("test", true)
|
||||
idx = NewUpsideDownCouch(store)
|
||||
err = idx.Open()
|
||||
if err != nil {
|
||||
|
@ -63,7 +66,7 @@ func TestIndexOpenReopen(t *testing.T) {
|
|||
func TestIndexInsert(t *testing.T) {
|
||||
defer os.RemoveAll("test")
|
||||
|
||||
store, err := gouchstore.Open("test")
|
||||
store, err := leveldb.Open("test", true)
|
||||
idx := NewUpsideDownCouch(store)
|
||||
err = idx.Open()
|
||||
if err != nil {
|
||||
|
@ -101,7 +104,7 @@ func TestIndexInsert(t *testing.T) {
|
|||
func TestIndexInsertThenDelete(t *testing.T) {
|
||||
defer os.RemoveAll("test")
|
||||
|
||||
store, err := gouchstore.Open("test")
|
||||
store, err := leveldb.Open("test", true)
|
||||
idx := NewUpsideDownCouch(store)
|
||||
err = idx.Open()
|
||||
if err != nil {
|
||||
|
@ -169,7 +172,7 @@ func TestIndexInsertThenDelete(t *testing.T) {
|
|||
func TestIndexInsertThenUpdate(t *testing.T) {
|
||||
defer os.RemoveAll("test")
|
||||
|
||||
store, err := gouchstore.Open("test")
|
||||
store, err := leveldb.Open("test", true)
|
||||
idx := NewUpsideDownCouch(store)
|
||||
err = idx.Open()
|
||||
if err != nil {
|
||||
|
@ -218,7 +221,7 @@ func TestIndexInsertThenUpdate(t *testing.T) {
|
|||
func TestIndexInsertMultiple(t *testing.T) {
|
||||
defer os.RemoveAll("test")
|
||||
|
||||
store, err := gouchstore.Open("test")
|
||||
store, err := leveldb.Open("test", true)
|
||||
idx := NewUpsideDownCouch(store)
|
||||
err = idx.Open()
|
||||
if err != nil {
|
||||
|
@ -252,12 +255,13 @@ func TestIndexInsertMultiple(t *testing.T) {
|
|||
|
||||
// close and reopen and and one more to testing counting works correctly
|
||||
idx.Close()
|
||||
store, err = gouchstore.Open("test")
|
||||
store, err = leveldb.Open("test", true)
|
||||
idx = NewUpsideDownCouch(store)
|
||||
err = idx.Open()
|
||||
if err != nil {
|
||||
t.Errorf("error opening index: %v", err)
|
||||
}
|
||||
defer idx.Close()
|
||||
|
||||
doc = document.NewDocument("3")
|
||||
doc.AddField(document.NewTextField("name", []byte("test")))
|
||||
|
@ -276,7 +280,10 @@ func TestIndexInsertMultiple(t *testing.T) {
|
|||
func TestIndexInsertWithStore(t *testing.T) {
|
||||
defer os.RemoveAll("test")
|
||||
|
||||
store, err := gouchstore.Open("test")
|
||||
store, err := leveldb.Open("test", true)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
idx := NewUpsideDownCouch(store)
|
||||
err = idx.Open()
|
||||
if err != nil {
|
||||
|
@ -326,3 +333,493 @@ func TestIndexInsertWithStore(t *testing.T) {
|
|||
t.Errorf("expected field content 'test', got '%s'", string(textField.Value()))
|
||||
}
|
||||
}
|
||||
|
||||
func TestIndexInternalCRUD(t *testing.T) {
|
||||
defer os.RemoveAll("test")
|
||||
|
||||
store, err := leveldb.Open("test", true)
|
||||
idx := NewUpsideDownCouch(store)
|
||||
err = idx.Open()
|
||||
if err != nil {
|
||||
t.Errorf("error opening index: %v", err)
|
||||
}
|
||||
defer idx.Close()
|
||||
|
||||
// get something that doesnt exist yet
|
||||
val, err := idx.GetInternal([]byte("key"))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if val != nil {
|
||||
t.Errorf("expected nil, got %s", val)
|
||||
}
|
||||
|
||||
// set
|
||||
err = idx.SetInternal([]byte("key"), []byte("abc"))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// get
|
||||
val, err = idx.GetInternal([]byte("key"))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if string(val) != "abc" {
|
||||
t.Errorf("expected %s, got '%s'", "abc", val)
|
||||
}
|
||||
|
||||
// delete
|
||||
err = idx.DeleteInternal([]byte("key"))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// get again
|
||||
val, err = idx.GetInternal([]byte("key"))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if val != nil {
|
||||
t.Errorf("expected nil, got %s", val)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIndexBatch(t *testing.T) {
|
||||
defer os.RemoveAll("test")
|
||||
|
||||
store, err := leveldb.Open("test", true)
|
||||
idx := NewUpsideDownCouch(store)
|
||||
err = idx.Open()
|
||||
if err != nil {
|
||||
t.Errorf("error opening index: %v", err)
|
||||
}
|
||||
defer idx.Close()
|
||||
|
||||
var expectedCount uint64 = 0
|
||||
|
||||
// first create 2 docs the old fashioned way
|
||||
doc := document.NewDocument("1")
|
||||
doc.AddField(document.NewTextField("name", []byte("test")))
|
||||
err = idx.Update(doc)
|
||||
if err != nil {
|
||||
t.Errorf("Error updating index: %v", err)
|
||||
}
|
||||
expectedCount += 1
|
||||
|
||||
doc = document.NewDocument("2")
|
||||
doc.AddField(document.NewTextField("name", []byte("test2")))
|
||||
err = idx.Update(doc)
|
||||
if err != nil {
|
||||
t.Errorf("Error updating index: %v", err)
|
||||
}
|
||||
expectedCount += 1
|
||||
|
||||
// now create a batch which does 3 things
|
||||
// insert new doc
|
||||
// update existing doc
|
||||
// delete existing doc
|
||||
// net document count change 0
|
||||
|
||||
batch := make(index.Batch, 0)
|
||||
doc = document.NewDocument("3")
|
||||
doc.AddField(document.NewTextField("name", []byte("test3")))
|
||||
batch["3"] = doc
|
||||
doc = document.NewDocument("2")
|
||||
doc.AddField(document.NewTextField("name", []byte("test2updated")))
|
||||
batch["2"] = doc
|
||||
batch["1"] = nil
|
||||
|
||||
err = idx.Batch(batch)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
docCount := idx.DocCount()
|
||||
if docCount != expectedCount {
|
||||
t.Errorf("Expected document count to be %d got %d", expectedCount, docCount)
|
||||
}
|
||||
|
||||
docIdReader, err := idx.DocIdReader("", "")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
docIds := make([]string, 0)
|
||||
docId, err := docIdReader.Next()
|
||||
for docId != "" && err == nil {
|
||||
docIds = append(docIds, docId)
|
||||
docId, err = docIdReader.Next()
|
||||
}
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
expectedDocIds := []string{"2", "3"}
|
||||
if !reflect.DeepEqual(docIds, expectedDocIds) {
|
||||
t.Errorf("expected ids: %v, got ids: %v", expectedDocIds, docIds)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIndexInsertUpdateDeleteWithMultipleTypesStored(t *testing.T) {
|
||||
defer os.RemoveAll("test")
|
||||
|
||||
store, err := leveldb.Open("test", true)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
idx := NewUpsideDownCouch(store)
|
||||
err = idx.Open()
|
||||
if err != nil {
|
||||
t.Errorf("error opening index: %v", err)
|
||||
}
|
||||
defer idx.Close()
|
||||
|
||||
var expectedCount uint64 = 0
|
||||
docCount := idx.DocCount()
|
||||
if docCount != expectedCount {
|
||||
t.Errorf("Expected document count to be %d got %d", expectedCount, docCount)
|
||||
}
|
||||
|
||||
doc := document.NewDocument("1")
|
||||
doc.AddField(document.NewTextFieldWithIndexingOptions("name", []byte("test"), document.INDEX_FIELD|document.STORE_FIELD))
|
||||
doc.AddField(document.NewNumericFieldWithIndexingOptions("age", 35.99, document.INDEX_FIELD|document.STORE_FIELD))
|
||||
doc.AddField(document.NewDateTimeFieldWithIndexingOptions("unixEpoch", time.Unix(0, 0), document.INDEX_FIELD|document.STORE_FIELD))
|
||||
err = idx.Update(doc)
|
||||
if err != nil {
|
||||
t.Errorf("Error updating index: %v", err)
|
||||
}
|
||||
expectedCount += 1
|
||||
|
||||
docCount = idx.DocCount()
|
||||
if docCount != expectedCount {
|
||||
t.Errorf("Expected document count to be %d got %d", expectedCount, docCount)
|
||||
}
|
||||
|
||||
// should have 72 rows
|
||||
// 1 for version
|
||||
// 3 for schema fields
|
||||
// 1 for text term
|
||||
// 16 for numeric terms
|
||||
// 16 for date terms
|
||||
// 3 for the stored field
|
||||
// 1 for the text term count
|
||||
// 16 for numeric term counts
|
||||
// 16 for date term counts
|
||||
// 1 for the back index entry
|
||||
expectedLength := uint64(1 + 3 + 1 + (64 / document.DEFAULT_PRECISION_STEP) + (64 / document.DEFAULT_PRECISION_STEP) + 3 + 1 + (64 / document.DEFAULT_PRECISION_STEP) + (64 / document.DEFAULT_PRECISION_STEP) + 1)
|
||||
rowCount := idx.rowCount()
|
||||
if rowCount != expectedLength {
|
||||
t.Errorf("expected %d rows, got: %d", expectedLength, rowCount)
|
||||
}
|
||||
|
||||
storedDoc, err := idx.Document("1")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if len(storedDoc.Fields) != 3 {
|
||||
t.Errorf("expected 3 stored field, got %d", len(storedDoc.Fields))
|
||||
}
|
||||
textField, ok := storedDoc.Fields[0].(*document.TextField)
|
||||
if !ok {
|
||||
t.Errorf("expected text field")
|
||||
}
|
||||
if string(textField.Value()) != "test" {
|
||||
t.Errorf("expected field content 'test', got '%s'", string(textField.Value()))
|
||||
}
|
||||
numField, ok := storedDoc.Fields[1].(*document.NumericField)
|
||||
if !ok {
|
||||
t.Errorf("expected numeric field")
|
||||
}
|
||||
numFieldNumer, err := numField.Number()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else {
|
||||
if numFieldNumer != 35.99 {
|
||||
t.Errorf("expeted numeric value 35.99, got %f", numFieldNumer)
|
||||
}
|
||||
}
|
||||
dateField, ok := storedDoc.Fields[2].(*document.DateTimeField)
|
||||
if !ok {
|
||||
t.Errorf("expected date field")
|
||||
}
|
||||
dateFieldDate, err := dateField.DateTime()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else {
|
||||
if dateFieldDate != time.Unix(0, 0) {
|
||||
t.Errorf("expected date value unix epoch, got %v", dateFieldDate)
|
||||
}
|
||||
}
|
||||
|
||||
// now update the document, but omit one of the fields
|
||||
doc = document.NewDocument("1")
|
||||
doc.AddField(document.NewTextFieldWithIndexingOptions("name", []byte("testup"), document.INDEX_FIELD|document.STORE_FIELD))
|
||||
doc.AddField(document.NewNumericFieldWithIndexingOptions("age", 36.99, document.INDEX_FIELD|document.STORE_FIELD))
|
||||
err = idx.Update(doc)
|
||||
if err != nil {
|
||||
t.Errorf("Error updating index: %v", err)
|
||||
}
|
||||
|
||||
// expected doc count shouldn't have changed
|
||||
docCount = idx.DocCount()
|
||||
if docCount != expectedCount {
|
||||
t.Errorf("Expected document count to be %d got %d", expectedCount, docCount)
|
||||
}
|
||||
|
||||
// should only get 2 fields back now though
|
||||
storedDoc, err = idx.Document("1")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if len(storedDoc.Fields) != 2 {
|
||||
t.Errorf("expected 3 stored field, got %d", len(storedDoc.Fields))
|
||||
}
|
||||
textField, ok = storedDoc.Fields[0].(*document.TextField)
|
||||
if !ok {
|
||||
t.Errorf("expected text field")
|
||||
}
|
||||
if string(textField.Value()) != "testup" {
|
||||
t.Errorf("expected field content 'testup', got '%s'", string(textField.Value()))
|
||||
}
|
||||
numField, ok = storedDoc.Fields[1].(*document.NumericField)
|
||||
if !ok {
|
||||
t.Errorf("expected numeric field")
|
||||
}
|
||||
numFieldNumer, err = numField.Number()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else {
|
||||
if numFieldNumer != 36.99 {
|
||||
t.Errorf("expeted numeric value 36.99, got %f", numFieldNumer)
|
||||
}
|
||||
}
|
||||
|
||||
// now delete the document
|
||||
err = idx.Delete("1")
|
||||
expectedCount--
|
||||
|
||||
// expected doc count shouldn't have changed
|
||||
docCount = idx.DocCount()
|
||||
if docCount != expectedCount {
|
||||
t.Errorf("Expected document count to be %d got %d", expectedCount, docCount)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIndexInsertFields(t *testing.T) {
|
||||
defer os.RemoveAll("test")
|
||||
|
||||
store, err := leveldb.Open("test", true)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
idx := NewUpsideDownCouch(store)
|
||||
err = idx.Open()
|
||||
if err != nil {
|
||||
t.Errorf("error opening index: %v", err)
|
||||
}
|
||||
defer idx.Close()
|
||||
|
||||
doc := document.NewDocument("1")
|
||||
doc.AddField(document.NewTextFieldWithIndexingOptions("name", []byte("test"), document.INDEX_FIELD|document.STORE_FIELD))
|
||||
doc.AddField(document.NewNumericFieldWithIndexingOptions("age", 35.99, document.INDEX_FIELD|document.STORE_FIELD))
|
||||
doc.AddField(document.NewDateTimeFieldWithIndexingOptions("unixEpoch", time.Unix(0, 0), document.INDEX_FIELD|document.STORE_FIELD))
|
||||
err = idx.Update(doc)
|
||||
if err != nil {
|
||||
t.Errorf("Error updating index: %v", err)
|
||||
}
|
||||
|
||||
fields, err := idx.Fields()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else {
|
||||
expectedFields := []string{"name", "age", "unixEpoch"}
|
||||
if !reflect.DeepEqual(fields, expectedFields) {
|
||||
t.Errorf("expected fields: %v, got %v", expectedFields, fields)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestIndexUpdateComposites(t *testing.T) {
|
||||
defer os.RemoveAll("test")
|
||||
|
||||
store, err := leveldb.Open("test", true)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
idx := NewUpsideDownCouch(store)
|
||||
err = idx.Open()
|
||||
if err != nil {
|
||||
t.Errorf("error opening index: %v", err)
|
||||
}
|
||||
defer idx.Close()
|
||||
|
||||
doc := document.NewDocument("1")
|
||||
doc.AddField(document.NewTextFieldWithIndexingOptions("name", []byte("test"), document.INDEX_FIELD|document.STORE_FIELD))
|
||||
doc.AddField(document.NewTextFieldWithIndexingOptions("title", []byte("mister"), document.INDEX_FIELD|document.STORE_FIELD))
|
||||
doc.AddField(document.NewCompositeFieldWithIndexingOptions("_all", true, nil, nil, document.INDEX_FIELD))
|
||||
err = idx.Update(doc)
|
||||
if err != nil {
|
||||
t.Errorf("Error updating index: %v", err)
|
||||
}
|
||||
|
||||
// should have 72 rows
|
||||
// 1 for version
|
||||
// 3 for schema fields
|
||||
// 4 for text term
|
||||
// 2 for the stored field
|
||||
// 4 for the text term count
|
||||
// 1 for the back index entry
|
||||
expectedLength := uint64(1 + 3 + 4 + 2 + 4 + 1)
|
||||
rowCount := idx.rowCount()
|
||||
if rowCount != expectedLength {
|
||||
t.Errorf("expected %d rows, got: %d", expectedLength, rowCount)
|
||||
}
|
||||
|
||||
// now lets update it
|
||||
doc = document.NewDocument("1")
|
||||
doc.AddField(document.NewTextFieldWithIndexingOptions("name", []byte("testupdated"), document.INDEX_FIELD|document.STORE_FIELD))
|
||||
doc.AddField(document.NewTextFieldWithIndexingOptions("title", []byte("misterupdated"), document.INDEX_FIELD|document.STORE_FIELD))
|
||||
doc.AddField(document.NewCompositeFieldWithIndexingOptions("_all", true, nil, nil, document.INDEX_FIELD))
|
||||
err = idx.Update(doc)
|
||||
if err != nil {
|
||||
t.Errorf("Error updating index: %v", err)
|
||||
}
|
||||
|
||||
// make sure new values are in index
|
||||
storedDoc, err := idx.Document("1")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if len(storedDoc.Fields) != 2 {
|
||||
t.Errorf("expected 2 stored field, got %d", len(storedDoc.Fields))
|
||||
}
|
||||
textField, ok := storedDoc.Fields[0].(*document.TextField)
|
||||
if !ok {
|
||||
t.Errorf("expected text field")
|
||||
}
|
||||
if string(textField.Value()) != "testupdated" {
|
||||
t.Errorf("expected field content 'test', got '%s'", string(textField.Value()))
|
||||
}
|
||||
|
||||
// should have the same row count as before
|
||||
rowCount = idx.rowCount()
|
||||
if rowCount != expectedLength {
|
||||
t.Errorf("expected %d rows, got: %d", expectedLength, rowCount)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIndexFieldsMisc(t *testing.T) {
|
||||
defer os.RemoveAll("test")
|
||||
|
||||
store, err := leveldb.Open("test", true)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
idx := NewUpsideDownCouch(store)
|
||||
err = idx.Open()
|
||||
if err != nil {
|
||||
t.Errorf("error opening index: %v", err)
|
||||
}
|
||||
defer idx.Close()
|
||||
|
||||
doc := document.NewDocument("1")
|
||||
doc.AddField(document.NewTextFieldWithIndexingOptions("name", []byte("test"), document.INDEX_FIELD|document.STORE_FIELD))
|
||||
doc.AddField(document.NewTextFieldWithIndexingOptions("title", []byte("mister"), document.INDEX_FIELD|document.STORE_FIELD))
|
||||
err = idx.Update(doc)
|
||||
if err != nil {
|
||||
t.Errorf("Error updating index: %v", err)
|
||||
}
|
||||
|
||||
fieldName1 := idx.fieldIndexToName(1)
|
||||
if fieldName1 != "name" {
|
||||
t.Errorf("expected field named 'name', got '%s'", fieldName1)
|
||||
}
|
||||
fieldName2 := idx.fieldIndexToName(2)
|
||||
if fieldName2 != "title" {
|
||||
t.Errorf("expected field named 'title', got '%s'", fieldName2)
|
||||
}
|
||||
fieldName3 := idx.fieldIndexToName(3)
|
||||
if fieldName3 != "" {
|
||||
t.Errorf("expected field named '', got '%s'", fieldName3)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestIndexTermReaderCompositeFields(t *testing.T) {
|
||||
defer os.RemoveAll("test")
|
||||
|
||||
store, err := leveldb.Open("test", true)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
idx := NewUpsideDownCouch(store)
|
||||
err = idx.Open()
|
||||
if err != nil {
|
||||
t.Errorf("error opening index: %v", err)
|
||||
}
|
||||
defer idx.Close()
|
||||
|
||||
doc := document.NewDocument("1")
|
||||
doc.AddField(document.NewTextFieldWithIndexingOptions("name", []byte("test"), document.INDEX_FIELD|document.STORE_FIELD|document.INCLUDE_TERM_VECTORS))
|
||||
doc.AddField(document.NewTextFieldWithIndexingOptions("title", []byte("mister"), document.INDEX_FIELD|document.STORE_FIELD|document.INCLUDE_TERM_VECTORS))
|
||||
doc.AddField(document.NewCompositeFieldWithIndexingOptions("_all", true, nil, nil, document.INDEX_FIELD|document.INCLUDE_TERM_VECTORS))
|
||||
err = idx.Update(doc)
|
||||
if err != nil {
|
||||
t.Errorf("Error updating index: %v", err)
|
||||
}
|
||||
|
||||
termFieldReader, err := idx.TermFieldReader([]byte("mister"), "_all")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
tfd, err := termFieldReader.Next()
|
||||
for tfd != nil && err == nil {
|
||||
if tfd.ID != "1" {
|
||||
t.Errorf("expected to find document id 1")
|
||||
}
|
||||
tfd, err = termFieldReader.Next()
|
||||
}
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIndexDocumentFieldTerms(t *testing.T) {
|
||||
defer os.RemoveAll("test")
|
||||
|
||||
store, err := leveldb.Open("test", true)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
idx := NewUpsideDownCouch(store)
|
||||
err = idx.Open()
|
||||
if err != nil {
|
||||
t.Errorf("error opening index: %v", err)
|
||||
}
|
||||
defer idx.Close()
|
||||
|
||||
doc := document.NewDocument("1")
|
||||
doc.AddField(document.NewTextFieldWithIndexingOptions("name", []byte("test"), document.INDEX_FIELD|document.STORE_FIELD|document.INCLUDE_TERM_VECTORS))
|
||||
doc.AddField(document.NewTextFieldWithIndexingOptions("title", []byte("mister"), document.INDEX_FIELD|document.STORE_FIELD|document.INCLUDE_TERM_VECTORS))
|
||||
doc.AddField(document.NewCompositeFieldWithIndexingOptions("_all", true, nil, nil, document.INDEX_FIELD|document.INCLUDE_TERM_VECTORS))
|
||||
err = idx.Update(doc)
|
||||
if err != nil {
|
||||
t.Errorf("Error updating index: %v", err)
|
||||
}
|
||||
|
||||
fieldTerms, err := idx.DocumentFieldTerms("1")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
expectedFieldTerms := index.FieldTerms{
|
||||
"name": []string{"test"},
|
||||
"title": []string{"mister"},
|
||||
"_all": []string{"test", "mister"},
|
||||
}
|
||||
if !reflect.DeepEqual(fieldTerms, expectedFieldTerms) {
|
||||
t.Errorf("expected field terms: %#v, got: %#v", expectedFieldTerms, fieldTerms)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user