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
|
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) {
|
func (udc *UpsideDownCouch) Fields() ([]string, error) {
|
||||||
rv := make([]string, 0)
|
rv := make([]string, 0)
|
||||||
it := udc.store.Iterator([]byte{'f'})
|
it := udc.store.Iterator([]byte{'f'})
|
||||||
|
@ -553,71 +532,6 @@ func (udc *UpsideDownCouch) Fields() ([]string, error) {
|
||||||
return rv, nil
|
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) {
|
func (udc *UpsideDownCouch) TermFieldReader(term []byte, fieldName string) (index.TermFieldReader, error) {
|
||||||
fieldIndex, fieldExists := udc.fieldIndexes[fieldName]
|
fieldIndex, fieldExists := udc.fieldIndexes[fieldName]
|
||||||
if fieldExists {
|
if fieldExists {
|
||||||
|
@ -793,17 +707,97 @@ func (udc *UpsideDownCouch) SetInternal(key, val []byte) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (udc *UpsideDownCouch) GetInternal(key []byte) ([]byte, error) {
|
func (udc *UpsideDownCouch) GetInternal(key []byte) ([]byte, error) {
|
||||||
internalRow, err := NewInternalRowKV(key, nil)
|
internalRow := NewInternalRow(key, nil)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return udc.store.Get(internalRow.Key())
|
return udc.store.Get(internalRow.Key())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (udc *UpsideDownCouch) DeleteInternal(key []byte) error {
|
func (udc *UpsideDownCouch) DeleteInternal(key []byte) error {
|
||||||
internalRow, err := NewInternalRowKV(key, nil)
|
internalRow := NewInternalRow(key, nil)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return udc.store.Delete(internalRow.Key())
|
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 (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/couchbaselabs/bleve/analysis"
|
"github.com/couchbaselabs/bleve/analysis"
|
||||||
"github.com/couchbaselabs/bleve/analysis/tokenizers/regexp_tokenizer"
|
"github.com/couchbaselabs/bleve/analysis/tokenizers/regexp_tokenizer"
|
||||||
"github.com/couchbaselabs/bleve/document"
|
"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{
|
var testAnalyzer = &analysis.Analyzer{
|
||||||
|
@ -26,7 +29,7 @@ var testAnalyzer = &analysis.Analyzer{
|
||||||
func TestIndexOpenReopen(t *testing.T) {
|
func TestIndexOpenReopen(t *testing.T) {
|
||||||
defer os.RemoveAll("test")
|
defer os.RemoveAll("test")
|
||||||
|
|
||||||
store, err := gouchstore.Open("test")
|
store, err := leveldb.Open("test", true)
|
||||||
idx := NewUpsideDownCouch(store)
|
idx := NewUpsideDownCouch(store)
|
||||||
err = idx.Open()
|
err = idx.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -49,7 +52,7 @@ func TestIndexOpenReopen(t *testing.T) {
|
||||||
// now close it
|
// now close it
|
||||||
idx.Close()
|
idx.Close()
|
||||||
|
|
||||||
store, err = gouchstore.Open("test")
|
store, err = leveldb.Open("test", true)
|
||||||
idx = NewUpsideDownCouch(store)
|
idx = NewUpsideDownCouch(store)
|
||||||
err = idx.Open()
|
err = idx.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -63,7 +66,7 @@ func TestIndexOpenReopen(t *testing.T) {
|
||||||
func TestIndexInsert(t *testing.T) {
|
func TestIndexInsert(t *testing.T) {
|
||||||
defer os.RemoveAll("test")
|
defer os.RemoveAll("test")
|
||||||
|
|
||||||
store, err := gouchstore.Open("test")
|
store, err := leveldb.Open("test", true)
|
||||||
idx := NewUpsideDownCouch(store)
|
idx := NewUpsideDownCouch(store)
|
||||||
err = idx.Open()
|
err = idx.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -101,7 +104,7 @@ func TestIndexInsert(t *testing.T) {
|
||||||
func TestIndexInsertThenDelete(t *testing.T) {
|
func TestIndexInsertThenDelete(t *testing.T) {
|
||||||
defer os.RemoveAll("test")
|
defer os.RemoveAll("test")
|
||||||
|
|
||||||
store, err := gouchstore.Open("test")
|
store, err := leveldb.Open("test", true)
|
||||||
idx := NewUpsideDownCouch(store)
|
idx := NewUpsideDownCouch(store)
|
||||||
err = idx.Open()
|
err = idx.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -169,7 +172,7 @@ func TestIndexInsertThenDelete(t *testing.T) {
|
||||||
func TestIndexInsertThenUpdate(t *testing.T) {
|
func TestIndexInsertThenUpdate(t *testing.T) {
|
||||||
defer os.RemoveAll("test")
|
defer os.RemoveAll("test")
|
||||||
|
|
||||||
store, err := gouchstore.Open("test")
|
store, err := leveldb.Open("test", true)
|
||||||
idx := NewUpsideDownCouch(store)
|
idx := NewUpsideDownCouch(store)
|
||||||
err = idx.Open()
|
err = idx.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -218,7 +221,7 @@ func TestIndexInsertThenUpdate(t *testing.T) {
|
||||||
func TestIndexInsertMultiple(t *testing.T) {
|
func TestIndexInsertMultiple(t *testing.T) {
|
||||||
defer os.RemoveAll("test")
|
defer os.RemoveAll("test")
|
||||||
|
|
||||||
store, err := gouchstore.Open("test")
|
store, err := leveldb.Open("test", true)
|
||||||
idx := NewUpsideDownCouch(store)
|
idx := NewUpsideDownCouch(store)
|
||||||
err = idx.Open()
|
err = idx.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -252,12 +255,13 @@ func TestIndexInsertMultiple(t *testing.T) {
|
||||||
|
|
||||||
// close and reopen and and one more to testing counting works correctly
|
// close and reopen and and one more to testing counting works correctly
|
||||||
idx.Close()
|
idx.Close()
|
||||||
store, err = gouchstore.Open("test")
|
store, err = leveldb.Open("test", true)
|
||||||
idx = NewUpsideDownCouch(store)
|
idx = NewUpsideDownCouch(store)
|
||||||
err = idx.Open()
|
err = idx.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("error opening index: %v", err)
|
t.Errorf("error opening index: %v", err)
|
||||||
}
|
}
|
||||||
|
defer idx.Close()
|
||||||
|
|
||||||
doc = document.NewDocument("3")
|
doc = document.NewDocument("3")
|
||||||
doc.AddField(document.NewTextField("name", []byte("test")))
|
doc.AddField(document.NewTextField("name", []byte("test")))
|
||||||
|
@ -276,7 +280,10 @@ func TestIndexInsertMultiple(t *testing.T) {
|
||||||
func TestIndexInsertWithStore(t *testing.T) {
|
func TestIndexInsertWithStore(t *testing.T) {
|
||||||
defer os.RemoveAll("test")
|
defer os.RemoveAll("test")
|
||||||
|
|
||||||
store, err := gouchstore.Open("test")
|
store, err := leveldb.Open("test", true)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
idx := NewUpsideDownCouch(store)
|
idx := NewUpsideDownCouch(store)
|
||||||
err = idx.Open()
|
err = idx.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -326,3 +333,493 @@ func TestIndexInsertWithStore(t *testing.T) {
|
||||||
t.Errorf("expected field content 'test', got '%s'", string(textField.Value()))
|
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