2016-08-20 20:03:46 +02:00
// 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 smolder
import (
"log"
"reflect"
"regexp"
"strconv"
"sync"
"testing"
"time"
"github.com/blevesearch/bleve/analysis"
"github.com/blevesearch/bleve/analysis/analyzers/standard_analyzer"
"github.com/blevesearch/bleve/analysis/tokenizers/regexp_tokenizer"
"github.com/blevesearch/bleve/document"
"github.com/blevesearch/bleve/index"
"github.com/blevesearch/bleve/index/store/boltdb"
"github.com/blevesearch/bleve/index/store/null"
"github.com/blevesearch/bleve/registry"
)
var testAnalyzer = & analysis . Analyzer {
Tokenizer : regexp_tokenizer . NewRegexpTokenizer ( regexp . MustCompile ( ` \w+ ` ) ) ,
}
func TestIndexOpenReopen ( t * testing . T ) {
defer func ( ) {
err := DestroyTest ( )
if err != nil {
t . Fatal ( err )
}
} ( )
analysisQueue := index . NewAnalysisQueue ( 1 )
idx , err := NewSmolderingCouch ( boltdb . Name , boltTestConfig , analysisQueue )
if err != nil {
t . Fatal ( err )
}
err = idx . Open ( )
if err != nil {
t . Errorf ( "error opening index: %v" , err )
}
var expectedCount uint64
2016-09-13 18:40:01 +02:00
reader , err := idx . Reader ( )
if err != nil {
t . Fatal ( err )
}
docCount , err := reader . DocCount ( )
2016-08-20 20:03:46 +02:00
if err != nil {
t . Error ( err )
}
if docCount != expectedCount {
t . Errorf ( "Expected document count to be %d got %d" , expectedCount , docCount )
}
2016-09-13 18:40:01 +02:00
err = reader . Close ( )
if err != nil {
t . Fatal ( err )
}
2016-08-20 20:03:46 +02:00
// opening the database should have inserted a version and _id field
expectedLength := uint64 ( 2 )
rowCount , err := idx . ( * SmolderingCouch ) . rowCount ( )
if err != nil {
t . Error ( err )
}
if rowCount != expectedLength {
t . Errorf ( "expected %d rows, got: %d" , expectedLength , rowCount )
}
// now close it
err = idx . Close ( )
if err != nil {
t . Fatal ( err )
}
idx , err = NewSmolderingCouch ( boltdb . Name , boltTestConfig , analysisQueue )
if err != nil {
t . Fatal ( err )
}
err = idx . Open ( )
if err != nil {
t . Errorf ( "error opening index: %v" , err )
}
// now close it
err = idx . Close ( )
if err != nil {
t . Fatal ( err )
}
}
func TestIndexInsert ( t * testing . T ) {
defer func ( ) {
err := DestroyTest ( )
if err != nil {
t . Fatal ( err )
}
} ( )
analysisQueue := index . NewAnalysisQueue ( 1 )
idx , err := NewSmolderingCouch ( boltdb . Name , boltTestConfig , analysisQueue )
if err != nil {
t . Fatal ( err )
}
err = idx . Open ( )
if err != nil {
t . Errorf ( "error opening index: %v" , err )
}
defer func ( ) {
err := idx . Close ( )
if err != nil {
t . Fatal ( err )
}
} ( )
var expectedCount uint64
2016-09-13 18:40:01 +02:00
reader , err := idx . Reader ( )
if err != nil {
t . Fatal ( err )
}
docCount , err := reader . DocCount ( )
2016-08-20 20:03:46 +02:00
if err != nil {
t . Error ( err )
}
if docCount != expectedCount {
t . Errorf ( "Expected document count to be %d got %d" , expectedCount , docCount )
}
2016-09-13 18:40:01 +02:00
err = reader . Close ( )
if err != nil {
t . Fatal ( err )
}
2016-08-20 20:03:46 +02:00
doc := document . NewDocument ( "1" )
doc . AddField ( document . NewTextField ( "name" , [ ] uint64 { } , [ ] byte ( "test" ) ) )
err = idx . Update ( doc )
if err != nil {
t . Errorf ( "Error updating index: %v" , err )
}
expectedCount ++
2016-09-13 18:40:01 +02:00
reader , err = idx . Reader ( )
if err != nil {
t . Fatal ( err )
}
docCount , err = reader . DocCount ( )
2016-08-20 20:03:46 +02:00
if err != nil {
t . Error ( err )
}
if docCount != expectedCount {
t . Errorf ( "Expected document count to be %d got %d" , expectedCount , docCount )
}
2016-09-13 18:40:01 +02:00
err = reader . Close ( )
if err != nil {
t . Fatal ( err )
}
2016-08-20 20:03:46 +02:00
// should have 4 rows (1 for version, 1 for schema field, and 1 for single term, and 1 for the term count, and 1 for the back index entry)
// +1 for id term
2016-09-09 17:04:11 +02:00
// +1 for id stored
2016-08-20 20:03:46 +02:00
// +1 for id term dictionary
// +1 for id field def
2016-09-09 17:04:11 +02:00
expectedLength := uint64 ( 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 )
2016-08-20 20:03:46 +02:00
rowCount , err := idx . ( * SmolderingCouch ) . rowCount ( )
if err != nil {
t . Error ( err )
}
if rowCount != expectedLength {
t . Errorf ( "expected %d rows, got: %d" , expectedLength , rowCount )
}
}
func TestIndexInsertThenDelete ( t * testing . T ) {
defer func ( ) {
err := DestroyTest ( )
if err != nil {
t . Fatal ( err )
}
} ( )
analysisQueue := index . NewAnalysisQueue ( 1 )
idx , err := NewSmolderingCouch ( boltdb . Name , boltTestConfig , analysisQueue )
if err != nil {
t . Fatal ( err )
}
err = idx . Open ( )
if err != nil {
t . Errorf ( "error opening index: %v" , err )
}
expectedRows := 2
defer func ( ) {
err := idx . Close ( )
if err != nil {
t . Fatal ( err )
}
} ( )
var expectedCount uint64
2016-09-13 18:40:01 +02:00
reader , err := idx . Reader ( )
if err != nil {
t . Fatal ( err )
}
docCount , err := reader . DocCount ( )
2016-08-20 20:03:46 +02:00
if err != nil {
t . Error ( err )
}
if docCount != expectedCount {
t . Errorf ( "Expected document count to be %d got %d" , expectedCount , docCount )
}
2016-09-13 18:40:01 +02:00
err = reader . Close ( )
if err != nil {
t . Fatal ( err )
}
2016-08-20 20:03:46 +02:00
doc := document . NewDocument ( "1" )
doc . AddField ( document . NewTextField ( "name" , [ ] uint64 { } , [ ] byte ( "test" ) ) )
err = idx . Update ( doc )
if err != nil {
t . Errorf ( "Error updating index: %v" , err )
}
expectedCount ++
expectedRows += 4 // 2 dictionary 2 terms
doc2 := document . NewDocument ( "2" )
doc2 . AddField ( document . NewTextField ( "name" , [ ] uint64 { } , [ ] byte ( "test" ) ) )
err = idx . Update ( doc2 )
if err != nil {
t . Errorf ( "Error updating index: %v" , err )
}
expectedCount ++
expectedRows += 4 // 2 dictionary 2 terms
2016-09-13 18:40:01 +02:00
reader , err = idx . Reader ( )
if err != nil {
t . Fatal ( err )
}
docCount , err = reader . DocCount ( )
2016-08-20 20:03:46 +02:00
if err != nil {
t . Error ( err )
}
if docCount != expectedCount {
t . Errorf ( "Expected document count to be %d got %d" , expectedCount , docCount )
}
2016-09-13 18:40:01 +02:00
err = reader . Close ( )
if err != nil {
t . Fatal ( err )
}
2016-08-20 20:03:46 +02:00
err = idx . Delete ( "1" )
if err != nil {
t . Errorf ( "Error deleting entry from index: %v" , err )
}
expectedCount --
expectedRows -= 2 //2 terms
2016-09-13 18:40:01 +02:00
reader , err = idx . Reader ( )
if err != nil {
t . Fatal ( err )
}
docCount , err = reader . DocCount ( )
2016-08-20 20:03:46 +02:00
if err != nil {
t . Error ( err )
}
if docCount != expectedCount {
t . Errorf ( "Expected document count to be %d got %d" , expectedCount , docCount )
}
2016-09-13 18:40:01 +02:00
err = reader . Close ( )
if err != nil {
t . Fatal ( err )
}
2016-08-20 20:03:46 +02:00
err = idx . Delete ( "2" )
if err != nil {
t . Errorf ( "Error deleting entry from index: %v" , err )
}
expectedCount --
expectedRows -= 2 //2 terms
2016-09-13 18:40:01 +02:00
reader , err = idx . Reader ( )
if err != nil {
t . Fatal ( err )
}
docCount , err = reader . DocCount ( )
2016-08-20 20:03:46 +02:00
if err != nil {
t . Error ( err )
}
if docCount != expectedCount {
t . Errorf ( "Expected document count to be %d got %d" , expectedCount , docCount )
}
2016-09-13 18:40:01 +02:00
err = reader . Close ( )
if err != nil {
t . Fatal ( err )
}
2016-08-20 20:03:46 +02:00
// should have 2 rows (1 for version, 2 for schema field, 3 for dictionary row garbage)
//expectedLength := uint64(1 + 2 + 3)
rowCount , err := idx . ( * SmolderingCouch ) . rowCount ( )
if err != nil {
t . Error ( err )
}
if rowCount != uint64 ( expectedRows ) {
t . Errorf ( "expected %d rows, got: %d" , expectedRows , rowCount )
}
}
func TestIndexInsertThenUpdate ( t * testing . T ) {
defer func ( ) {
err := DestroyTest ( )
if err != nil {
t . Fatal ( err )
}
} ( )
analysisQueue := index . NewAnalysisQueue ( 1 )
idx , err := NewSmolderingCouch ( boltdb . Name , boltTestConfig , analysisQueue )
if err != nil {
t . Fatal ( err )
}
err = idx . Open ( )
if err != nil {
t . Errorf ( "error opening index: %v" , err )
}
defer func ( ) {
err := idx . Close ( )
if err != nil {
t . Fatal ( err )
}
} ( )
doc := document . NewDocument ( "1" )
doc . AddField ( document . NewTextField ( "name" , [ ] uint64 { } , [ ] byte ( "test" ) ) )
err = idx . Update ( doc )
if err != nil {
t . Errorf ( "Error updating index: %v" , err )
}
// this update should overwrite one term, and introduce one new one
doc = document . NewDocument ( "1" )
doc . AddField ( document . NewTextFieldWithAnalyzer ( "name" , [ ] uint64 { } , [ ] byte ( "test fail" ) , testAnalyzer ) )
err = idx . Update ( doc )
if err != nil {
t . Errorf ( "Error deleting entry from index: %v" , err )
}
2016-09-09 17:04:11 +02:00
// should have 2 rows (1 for version, 2 for schema field, and 3 for the two term, and 3 for the term counts, and 1 for the back index entry, and 1 for stord id)
expectedLength := uint64 ( 1 + 2 + 3 + 3 + 1 + 1 )
2016-08-20 20:03:46 +02:00
rowCount , err := idx . ( * SmolderingCouch ) . rowCount ( )
if err != nil {
t . Error ( err )
}
if rowCount != expectedLength {
t . Errorf ( "expected %d rows, got: %d" , expectedLength , rowCount )
2016-09-13 18:40:01 +02:00
reader , err := idx . Reader ( )
if err != nil {
t . Fatal ( err )
}
allRows := reader . DumpAll ( )
2016-08-20 20:03:46 +02:00
for ar := range allRows {
t . Logf ( "%v" , ar )
}
2016-09-13 18:40:01 +02:00
err = reader . Close ( )
if err != nil {
t . Fatal ( err )
}
2016-08-20 20:03:46 +02:00
}
// now do another update that should remove one of the terms
doc = document . NewDocument ( "1" )
doc . AddField ( document . NewTextField ( "name" , [ ] uint64 { } , [ ] byte ( "fail" ) ) )
err = idx . Update ( doc )
if err != nil {
t . Errorf ( "Error deleting entry from index: %v" , err )
}
2016-09-09 17:04:11 +02:00
// should have 2 rows (1 for version, 2 for schema field, and 2 for the remaining terms, and 2 for the term diciontary, and 1 for the back index entry, and 1 for stored id)
expectedLength = uint64 ( 1 + 2 + 2 + 3 + 1 + 1 )
2016-08-20 20:03:46 +02:00
rowCount , err = idx . ( * SmolderingCouch ) . rowCount ( )
if err != nil {
t . Error ( err )
}
if rowCount != expectedLength {
t . Errorf ( "expected %d rows, got: %d" , expectedLength , rowCount )
2016-09-13 18:40:01 +02:00
reader , err := idx . Reader ( )
if err != nil {
t . Fatal ( err )
}
allRows := reader . DumpAll ( )
2016-08-20 20:03:46 +02:00
for ar := range allRows {
t . Logf ( "%v" , ar )
}
2016-09-13 18:40:01 +02:00
if err != nil {
t . Fatal ( err )
}
2016-08-20 20:03:46 +02:00
}
}
func TestIndexInsertMultiple ( t * testing . T ) {
defer func ( ) {
err := DestroyTest ( )
if err != nil {
t . Fatal ( err )
}
} ( )
analysisQueue := index . NewAnalysisQueue ( 1 )
idx , err := NewSmolderingCouch ( boltdb . Name , boltTestConfig , analysisQueue )
if err != nil {
t . Fatal ( err )
}
err = idx . Open ( )
if err != nil {
t . Errorf ( "error opening index: %v" , err )
}
var expectedCount uint64
doc := document . NewDocument ( "1" )
doc . AddField ( document . NewTextField ( "name" , [ ] uint64 { } , [ ] byte ( "test" ) ) )
err = idx . Update ( doc )
if err != nil {
t . Errorf ( "Error updating index: %v" , err )
}
expectedCount ++
doc = document . NewDocument ( "2" )
doc . AddField ( document . NewTextField ( "name" , [ ] uint64 { } , [ ] byte ( "test" ) ) )
err = idx . Update ( doc )
if err != nil {
t . Errorf ( "Error updating index: %v" , err )
}
expectedCount ++
2016-09-09 17:04:11 +02:00
// should have 4 rows (1 for version, 1 for schema field, and 4 for terms, and 3 for the term count, and 2 for the back index entries, and 2 for stored ids)
expectedLength := uint64 ( 1 + 2 + 4 + 3 + 2 + 2 )
2016-08-20 20:03:46 +02:00
rowCount , err := idx . ( * SmolderingCouch ) . rowCount ( )
if err != nil {
t . Error ( err )
}
if rowCount != expectedLength {
t . Errorf ( "expected %d rows, got: %d" , expectedLength , rowCount )
}
// close, reopen and add one more to test that counting works correctly
err = idx . Close ( )
if err != nil {
t . Fatal ( err )
}
idx , err = NewSmolderingCouch ( boltdb . Name , boltTestConfig , analysisQueue )
if err != nil {
t . Fatal ( err )
}
err = idx . Open ( )
if err != nil {
t . Fatalf ( "error opening index: %v" , err )
}
defer func ( ) {
err := idx . Close ( )
if err != nil {
t . Fatal ( err )
}
} ( )
doc = document . NewDocument ( "3" )
doc . AddField ( document . NewTextField ( "name" , [ ] uint64 { } , [ ] byte ( "test" ) ) )
err = idx . Update ( doc )
if err != nil {
t . Errorf ( "Error updating index: %v" , err )
}
expectedCount ++
2016-09-13 18:40:01 +02:00
reader , err := idx . Reader ( )
if err != nil {
t . Fatal ( err )
}
docCount , err := reader . DocCount ( )
2016-08-20 20:03:46 +02:00
if err != nil {
t . Error ( err )
}
if docCount != expectedCount {
2016-09-13 18:40:01 +02:00
t . Errorf ( "Expected document count to be %d got %d" , expectedCount , docCount )
}
err = reader . Close ( )
if err != nil {
t . Fatal ( err )
2016-08-20 20:03:46 +02:00
}
}
func TestIndexInsertWithStore ( t * testing . T ) {
defer func ( ) {
err := DestroyTest ( )
if err != nil {
t . Fatal ( err )
}
} ( )
analysisQueue := index . NewAnalysisQueue ( 1 )
idx , err := NewSmolderingCouch ( boltdb . Name , boltTestConfig , analysisQueue )
if err != nil {
t . Fatal ( err )
}
err = idx . Open ( )
if err != nil {
t . Errorf ( "error opening index: %v" , err )
}
defer func ( ) {
err := idx . Close ( )
if err != nil {
t . Fatal ( err )
}
} ( )
var expectedCount uint64
2016-09-13 18:40:01 +02:00
reader , err := idx . Reader ( )
if err != nil {
t . Fatal ( err )
}
docCount , err := reader . DocCount ( )
2016-08-20 20:03:46 +02:00
if err != nil {
t . Error ( err )
}
if docCount != expectedCount {
t . Errorf ( "Expected document count to be %d got %d" , expectedCount , docCount )
}
2016-09-13 18:40:01 +02:00
err = reader . Close ( )
if err != nil {
t . Fatal ( err )
}
2016-08-20 20:03:46 +02:00
doc := document . NewDocument ( "1" )
doc . AddField ( document . NewTextFieldWithIndexingOptions ( "name" , [ ] uint64 { } , [ ] byte ( "test" ) , document . IndexField | document . StoreField ) )
err = idx . Update ( doc )
if err != nil {
t . Errorf ( "Error updating index: %v" , err )
}
expectedCount ++
2016-09-13 18:40:01 +02:00
reader , err = idx . Reader ( )
if err != nil {
t . Fatal ( err )
}
docCount , err = reader . DocCount ( )
2016-08-20 20:03:46 +02:00
if err != nil {
t . Error ( err )
}
if docCount != expectedCount {
t . Errorf ( "Expected document count to be %d got %d" , expectedCount , docCount )
}
2016-09-13 18:40:01 +02:00
err = reader . Close ( )
if err != nil {
t . Fatal ( err )
}
2016-08-20 20:03:46 +02:00
2016-09-09 17:04:11 +02:00
// should have 6 rows (1 for version, 2 for schema field, and 2 for terms, and 2 for the stored field and 2 for the term counts, and 1 for the back index entry)
expectedLength := uint64 ( 1 + 2 + 2 + 2 + 2 + 1 )
2016-08-20 20:03:46 +02:00
rowCount , err := idx . ( * SmolderingCouch ) . rowCount ( )
if err != nil {
t . Error ( err )
}
if rowCount != expectedLength {
t . Errorf ( "expected %d rows, got: %d" , expectedLength , rowCount )
}
indexReader , err := idx . Reader ( )
if err != nil {
t . Error ( err )
}
defer func ( ) {
err := indexReader . Close ( )
if err != nil {
t . Fatal ( err )
}
} ( )
storedDoc , err := indexReader . Document ( "1" )
if err != nil {
t . Error ( err )
}
2016-09-09 17:04:11 +02:00
if len ( storedDoc . Fields ) != 2 {
2016-08-20 20:03:46 +02:00
t . Errorf ( "expected 1 stored field, got %d" , len ( storedDoc . Fields ) )
}
2016-09-09 17:04:11 +02:00
for _ , f := range storedDoc . Fields {
if f . Name ( ) == "name" {
textField , ok := f . ( * 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 ( ) ) )
}
}
2016-08-20 20:03:46 +02:00
}
}
func TestIndexInternalCRUD ( t * testing . T ) {
defer func ( ) {
err := DestroyTest ( )
if err != nil {
t . Fatal ( err )
}
} ( )
analysisQueue := index . NewAnalysisQueue ( 1 )
idx , err := NewSmolderingCouch ( boltdb . Name , boltTestConfig , analysisQueue )
if err != nil {
t . Fatal ( err )
}
err = idx . Open ( )
if err != nil {
t . Errorf ( "error opening index: %v" , err )
}
defer func ( ) {
err := idx . Close ( )
if err != nil {
t . Fatal ( err )
}
} ( )
indexReader , err := idx . Reader ( )
if err != nil {
t . Error ( err )
}
// get something that doesn't exist yet
val , err := indexReader . GetInternal ( [ ] byte ( "key" ) )
if err != nil {
t . Error ( err )
}
if val != nil {
t . Errorf ( "expected nil, got %s" , val )
}
err = indexReader . Close ( )
if err != nil {
t . Fatal ( err )
}
// set
err = idx . SetInternal ( [ ] byte ( "key" ) , [ ] byte ( "abc" ) )
if err != nil {
t . Error ( err )
}
indexReader2 , err := idx . Reader ( )
if err != nil {
t . Error ( err )
}
// get
val , err = indexReader2 . GetInternal ( [ ] byte ( "key" ) )
if err != nil {
t . Error ( err )
}
if string ( val ) != "abc" {
t . Errorf ( "expected %s, got '%s'" , "abc" , val )
}
err = indexReader2 . Close ( )
if err != nil {
t . Fatal ( err )
}
// delete
err = idx . DeleteInternal ( [ ] byte ( "key" ) )
if err != nil {
t . Error ( err )
}
indexReader3 , err := idx . Reader ( )
if err != nil {
t . Error ( err )
}
// get again
val , err = indexReader3 . GetInternal ( [ ] byte ( "key" ) )
if err != nil {
t . Error ( err )
}
if val != nil {
t . Errorf ( "expected nil, got %s" , val )
}
err = indexReader3 . Close ( )
if err != nil {
t . Fatal ( err )
}
}
func TestIndexBatch ( t * testing . T ) {
defer func ( ) {
err := DestroyTest ( )
if err != nil {
t . Fatal ( err )
}
} ( )
analysisQueue := index . NewAnalysisQueue ( 1 )
idx , err := NewSmolderingCouch ( boltdb . Name , boltTestConfig , analysisQueue )
if err != nil {
t . Fatal ( err )
}
err = idx . Open ( )
if err != nil {
t . Errorf ( "error opening index: %v" , err )
}
defer func ( ) {
err := idx . Close ( )
if err != nil {
t . Fatal ( err )
}
} ( )
var expectedCount uint64
// first create 2 docs the old fashioned way
doc := document . NewDocument ( "1" )
doc . AddField ( document . NewTextField ( "name" , [ ] uint64 { } , [ ] byte ( "test" ) ) )
err = idx . Update ( doc )
if err != nil {
t . Errorf ( "Error updating index: %v" , err )
}
expectedCount ++
doc = document . NewDocument ( "2" )
doc . AddField ( document . NewTextField ( "name" , [ ] uint64 { } , [ ] byte ( "test2" ) ) )
err = idx . Update ( doc )
if err != nil {
t . Errorf ( "Error updating index: %v" , err )
}
expectedCount ++
// now create a batch which does 3 things
// insert new doc
// update existing doc
// delete existing doc
// net document count change 0
batch := index . NewBatch ( )
doc = document . NewDocument ( "3" )
doc . AddField ( document . NewTextField ( "name" , [ ] uint64 { } , [ ] byte ( "test3" ) ) )
batch . Update ( doc )
doc = document . NewDocument ( "2" )
doc . AddField ( document . NewTextField ( "name" , [ ] uint64 { } , [ ] byte ( "test2updated" ) ) )
batch . Update ( doc )
batch . Delete ( "1" )
err = idx . Batch ( batch )
if err != nil {
t . Error ( err )
}
indexReader , err := idx . Reader ( )
if err != nil {
t . Error ( err )
}
defer func ( ) {
err := indexReader . Close ( )
if err != nil {
t . Fatal ( err )
}
} ( )
2016-09-13 18:40:01 +02:00
docCount , err := indexReader . DocCount ( )
if err != nil {
t . Fatal ( err )
}
2016-08-20 20:03:46 +02:00
if docCount != expectedCount {
t . Errorf ( "Expected document count to be %d got %d" , expectedCount , docCount )
}
2016-09-09 17:04:11 +02:00
docIDReader , err := indexReader . DocIDReaderAll ( )
2016-08-20 20:03:46 +02:00
if err != nil {
t . Error ( err )
}
2016-09-09 21:42:08 +02:00
var docIDs [ ] string
2016-08-20 20:03:46 +02:00
docID , err := docIDReader . Next ( )
for docID != nil && err == nil {
2016-09-09 21:42:08 +02:00
// lookup external ID for this document
var extID string
extID , err = indexReader . ExternalID ( docID )
if err != nil {
t . Fatal ( err )
}
docIDs = append ( docIDs , extID )
2016-08-20 20:03:46 +02:00
docID , err = docIDReader . Next ( )
}
if err != nil {
t . Error ( err )
}
2016-09-09 21:42:08 +02:00
expectedDocIDs := [ ] string { "2" , "3" }
if ! reflect . DeepEqual ( docIDs , expectedDocIDs ) {
t . Errorf ( "expected ids: %v, got ids: %v" , expectedDocIDs , docIDs )
2016-09-13 18:40:01 +02:00
reader , err := idx . Reader ( )
if err != nil {
t . Fatal ( err )
}
allRows := reader . DumpAll ( )
2016-08-20 20:03:46 +02:00
for ar := range allRows {
t . Logf ( "%v" , ar )
}
2016-09-13 18:40:01 +02:00
err = reader . Close ( )
if err != nil {
t . Fatal ( err )
}
2016-08-20 20:03:46 +02:00
}
}
func TestIndexInsertUpdateDeleteWithMultipleTypesStored ( t * testing . T ) {
defer func ( ) {
err := DestroyTest ( )
if err != nil {
t . Fatal ( err )
}
} ( )
analysisQueue := index . NewAnalysisQueue ( 1 )
idx , err := NewSmolderingCouch ( boltdb . Name , boltTestConfig , analysisQueue )
if err != nil {
t . Fatal ( err )
}
err = idx . Open ( )
if err != nil {
t . Errorf ( "error opening index: %v" , err )
}
defer func ( ) {
err := idx . Close ( )
if err != nil {
t . Fatal ( err )
}
} ( )
var expectedCount uint64
2016-09-13 18:40:01 +02:00
reader , err := idx . Reader ( )
if err != nil {
t . Fatal ( err )
}
docCount , err := reader . DocCount ( )
2016-08-20 20:03:46 +02:00
if err != nil {
t . Error ( err )
}
if docCount != expectedCount {
t . Errorf ( "Expected document count to be %d got %d" , expectedCount , docCount )
}
2016-09-13 18:40:01 +02:00
err = reader . Close ( )
if err != nil {
t . Fatal ( err )
}
2016-08-20 20:03:46 +02:00
doc := document . NewDocument ( "1" )
doc . AddField ( document . NewTextFieldWithIndexingOptions ( "name" , [ ] uint64 { } , [ ] byte ( "test" ) , document . IndexField | document . StoreField ) )
doc . AddField ( document . NewNumericFieldWithIndexingOptions ( "age" , [ ] uint64 { } , 35.99 , document . IndexField | document . StoreField ) )
df , err := document . NewDateTimeFieldWithIndexingOptions ( "unixEpoch" , [ ] uint64 { } , time . Unix ( 0 , 0 ) , document . IndexField | document . StoreField )
if err != nil {
t . Error ( err )
}
doc . AddField ( df )
err = idx . Update ( doc )
if err != nil {
t . Errorf ( "Error updating index: %v" , err )
}
expectedCount ++
2016-09-13 18:40:01 +02:00
reader , err = idx . Reader ( )
if err != nil {
t . Fatal ( err )
}
docCount , err = reader . DocCount ( )
2016-08-20 20:03:46 +02:00
if err != nil {
t . Error ( err )
}
if docCount != expectedCount {
t . Errorf ( "Expected document count to be %d got %d" , expectedCount , docCount )
}
2016-09-13 18:40:01 +02:00
err = reader . Close ( )
if err != nil {
t . Fatal ( err )
}
2016-08-20 20:03:46 +02:00
2016-09-09 17:04:11 +02:00
// should have 78 rows
2016-08-20 20:03:46 +02:00
// 1 for version
// 4 for schema fields
// 1 for id term
// 1 for text term
// 16 for numeric terms
// 16 for date terms
2016-09-09 17:04:11 +02:00
// 4 for the stored field
2016-08-20 20:03:46 +02:00
// 1 for id term count
// 1 for the text term count
// 16 for numeric term counts
// 16 for date term counts
// 1 for the back index entry
2016-09-09 17:04:11 +02:00
expectedLength := uint64 ( 1 + 4 + 1 + 1 + ( 64 / document . DefaultPrecisionStep ) + ( 64 / document . DefaultPrecisionStep ) + 4 + 1 + 1 + ( 64 / document . DefaultPrecisionStep ) + ( 64 / document . DefaultPrecisionStep ) + 1 )
2016-08-20 20:03:46 +02:00
rowCount , err := idx . ( * SmolderingCouch ) . rowCount ( )
if err != nil {
t . Error ( err )
}
if rowCount != expectedLength {
t . Errorf ( "expected %d rows, got: %d" , expectedLength , rowCount )
}
indexReader , err := idx . Reader ( )
if err != nil {
t . Error ( err )
}
storedDoc , err := indexReader . Document ( "1" )
if err != nil {
t . Error ( err )
}
err = indexReader . Close ( )
if err != nil {
t . Error ( err )
}
2016-09-09 17:04:11 +02:00
if len ( storedDoc . Fields ) != 4 {
t . Errorf ( "expected 4 stored field, got %d" , len ( storedDoc . Fields ) )
2016-08-20 20:03:46 +02:00
}
2016-09-09 17:04:11 +02:00
for _ , f := range storedDoc . Fields {
if f . Name ( ) == "name" {
textField , ok := f . ( * 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 ( ) ) )
}
2016-08-20 20:03:46 +02:00
}
2016-09-09 17:04:11 +02:00
if f . Name ( ) == "age" {
numField , ok := f . ( * 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 )
}
}
}
if f . Name ( ) == "unixEpoch" {
dateField , ok := f . ( * 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 ) . UTC ( ) {
t . Errorf ( "expected date value unix epoch, got %v" , dateFieldDate )
}
}
2016-08-20 20:03:46 +02:00
}
}
// now update the document, but omit one of the fields
doc = document . NewDocument ( "1" )
doc . AddField ( document . NewTextFieldWithIndexingOptions ( "name" , [ ] uint64 { } , [ ] byte ( "testup" ) , document . IndexField | document . StoreField ) )
doc . AddField ( document . NewNumericFieldWithIndexingOptions ( "age" , [ ] uint64 { } , 36.99 , document . IndexField | document . StoreField ) )
err = idx . Update ( doc )
if err != nil {
t . Errorf ( "Error updating index: %v" , err )
}
indexReader2 , err := idx . Reader ( )
if err != nil {
t . Error ( err )
}
// expected doc count shouldn't have changed
2016-09-13 18:40:01 +02:00
docCount , err = indexReader2 . DocCount ( )
if err != nil {
t . Fatal ( err )
}
2016-08-20 20:03:46 +02:00
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 = indexReader2 . Document ( "1" )
if err != nil {
t . Error ( err )
}
err = indexReader2 . Close ( )
if err != nil {
t . Error ( err )
}
2016-09-09 17:04:11 +02:00
if len ( storedDoc . Fields ) != 3 {
2016-08-20 20:03:46 +02:00
t . Errorf ( "expected 3 stored field, got %d" , len ( storedDoc . Fields ) )
}
2016-09-09 17:04:11 +02:00
for _ , f := range storedDoc . Fields {
if f . Name ( ) == "name" {
textField , ok := f . ( * 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 ( ) ) )
}
}
if f . Name ( ) == "age" {
numField , ok := f . ( * 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 )
}
}
2016-08-20 20:03:46 +02:00
}
}
// now delete the document
err = idx . Delete ( "1" )
expectedCount --
// expected doc count shouldn't have changed
2016-09-13 18:40:01 +02:00
reader , err = idx . Reader ( )
if err != nil {
t . Fatal ( err )
}
docCount , err = reader . DocCount ( )
2016-08-20 20:03:46 +02:00
if err != nil {
t . Error ( err )
}
if docCount != expectedCount {
t . Errorf ( "Expected document count to be %d got %d" , expectedCount , docCount )
}
2016-09-13 18:40:01 +02:00
err = reader . Close ( )
if err != nil {
t . Fatal ( err )
}
2016-08-20 20:03:46 +02:00
}
func TestIndexInsertFields ( t * testing . T ) {
defer func ( ) {
err := DestroyTest ( )
if err != nil {
t . Fatal ( err )
}
} ( )
analysisQueue := index . NewAnalysisQueue ( 1 )
idx , err := NewSmolderingCouch ( boltdb . Name , boltTestConfig , analysisQueue )
if err != nil {
t . Fatal ( err )
}
err = idx . Open ( )
if err != nil {
t . Errorf ( "error opening index: %v" , err )
}
defer func ( ) {
err := idx . Close ( )
if err != nil {
t . Fatal ( err )
}
} ( )
doc := document . NewDocument ( "1" )
doc . AddField ( document . NewTextFieldWithIndexingOptions ( "name" , [ ] uint64 { } , [ ] byte ( "test" ) , document . IndexField | document . StoreField ) )
doc . AddField ( document . NewNumericFieldWithIndexingOptions ( "age" , [ ] uint64 { } , 35.99 , document . IndexField | document . StoreField ) )
dateField , err := document . NewDateTimeFieldWithIndexingOptions ( "unixEpoch" , [ ] uint64 { } , time . Unix ( 0 , 0 ) , document . IndexField | document . StoreField )
if err != nil {
t . Error ( err )
}
doc . AddField ( dateField )
err = idx . Update ( doc )
if err != nil {
t . Errorf ( "Error updating index: %v" , err )
}
indexReader , err := idx . Reader ( )
if err != nil {
t . Error ( err )
}
defer func ( ) {
err := indexReader . Close ( )
if err != nil {
t . Fatal ( err )
}
} ( )
fields , err := indexReader . Fields ( )
if err != nil {
t . Error ( err )
} else {
expectedFields := [ ] string { "_id" , "name" , "age" , "unixEpoch" }
if ! reflect . DeepEqual ( fields , expectedFields ) {
t . Errorf ( "expected fields: %v, got %v" , expectedFields , fields )
}
}
}
func TestIndexUpdateComposites ( t * testing . T ) {
defer func ( ) {
err := DestroyTest ( )
if err != nil {
t . Fatal ( err )
}
} ( )
analysisQueue := index . NewAnalysisQueue ( 1 )
idx , err := NewSmolderingCouch ( boltdb . Name , boltTestConfig , analysisQueue )
if err != nil {
t . Fatal ( err )
}
err = idx . Open ( )
if err != nil {
t . Errorf ( "error opening index: %v" , err )
}
defer func ( ) {
err := idx . Close ( )
if err != nil {
t . Fatal ( err )
}
} ( )
doc := document . NewDocument ( "1" )
doc . AddField ( document . NewTextFieldWithIndexingOptions ( "name" , [ ] uint64 { } , [ ] byte ( "test" ) , document . IndexField | document . StoreField ) )
doc . AddField ( document . NewTextFieldWithIndexingOptions ( "title" , [ ] uint64 { } , [ ] byte ( "mister" ) , document . IndexField | document . StoreField ) )
doc . AddField ( document . NewCompositeFieldWithIndexingOptions ( "_all" , true , nil , nil , document . IndexField ) )
err = idx . Update ( doc )
if err != nil {
t . Errorf ( "Error updating index: %v" , err )
}
// 1 for version
// 4 for schema fields
// 5 for text term
2016-09-09 17:04:11 +02:00
// 3 for the stored field
2016-08-20 20:03:46 +02:00
// 5 for the text term count
// 1 for the back index entry
2016-09-09 17:04:11 +02:00
expectedLength := uint64 ( 1 + 4 + 5 + 3 + 5 + 1 )
2016-08-20 20:03:46 +02:00
rowCount , err := idx . ( * SmolderingCouch ) . rowCount ( )
if err != nil {
t . Error ( err )
}
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" , [ ] uint64 { } , [ ] byte ( "testupdated" ) , document . IndexField | document . StoreField ) )
doc . AddField ( document . NewTextFieldWithIndexingOptions ( "title" , [ ] uint64 { } , [ ] byte ( "misterupdated" ) , document . IndexField | document . StoreField ) )
doc . AddField ( document . NewCompositeFieldWithIndexingOptions ( "_all" , true , nil , nil , document . IndexField ) )
err = idx . Update ( doc )
if err != nil {
t . Errorf ( "Error updating index: %v" , err )
}
indexReader , err := idx . Reader ( )
if err != nil {
t . Error ( err )
}
defer func ( ) {
err := indexReader . Close ( )
if err != nil {
t . Fatal ( err )
}
} ( )
// make sure new values are in index
storedDoc , err := indexReader . Document ( "1" )
if err != nil {
t . Error ( err )
}
2016-09-09 17:04:11 +02:00
if len ( storedDoc . Fields ) != 3 {
t . Errorf ( "expected 3 stored field, got %d" , len ( storedDoc . Fields ) )
2016-08-20 20:03:46 +02:00
}
2016-09-09 17:04:11 +02:00
for _ , f := range storedDoc . Fields {
if f . Name ( ) == "name" {
textField , ok := f . ( * 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 ( ) ) )
}
}
2016-08-20 20:03:46 +02:00
}
// should have the same row count as before, plus 4 term dictionary garbage rows
expectedLength += 4
rowCount , err = idx . ( * SmolderingCouch ) . rowCount ( )
if err != nil {
t . Error ( err )
}
if rowCount != expectedLength {
t . Errorf ( "expected %d rows, got: %d" , expectedLength , rowCount )
}
}
func TestIndexFieldsMisc ( t * testing . T ) {
defer func ( ) {
err := DestroyTest ( )
if err != nil {
t . Fatal ( err )
}
} ( )
analysisQueue := index . NewAnalysisQueue ( 1 )
idx , err := NewSmolderingCouch ( boltdb . Name , boltTestConfig , analysisQueue )
if err != nil {
t . Fatal ( err )
}
err = idx . Open ( )
if err != nil {
t . Errorf ( "error opening index: %v" , err )
}
defer func ( ) {
err := idx . Close ( )
if err != nil {
t . Fatal ( err )
}
} ( )
doc := document . NewDocument ( "1" )
doc . AddField ( document . NewTextFieldWithIndexingOptions ( "name" , [ ] uint64 { } , [ ] byte ( "test" ) , document . IndexField | document . StoreField ) )
doc . AddField ( document . NewTextFieldWithIndexingOptions ( "title" , [ ] uint64 { } , [ ] byte ( "mister" ) , document . IndexField | document . StoreField ) )
err = idx . Update ( doc )
if err != nil {
t . Errorf ( "Error updating index: %v" , err )
}
fieldName0 := idx . ( * SmolderingCouch ) . fieldCache . FieldIndexed ( 0 )
if fieldName0 != "_id" {
t . Errorf ( "expected field named '_id', got '%s'" , fieldName0 )
}
fieldName1 := idx . ( * SmolderingCouch ) . fieldCache . FieldIndexed ( 1 )
if fieldName1 != "name" {
t . Errorf ( "expected field named 'name', got '%s'" , fieldName1 )
}
fieldName2 := idx . ( * SmolderingCouch ) . fieldCache . FieldIndexed ( 2 )
if fieldName2 != "title" {
t . Errorf ( "expected field named 'title', got '%s'" , fieldName2 )
}
fieldName3 := idx . ( * SmolderingCouch ) . fieldCache . FieldIndexed ( 3 )
if fieldName3 != "" {
t . Errorf ( "expected field named '', got '%s'" , fieldName3 )
}
}
func TestIndexTermReaderCompositeFields ( t * testing . T ) {
defer func ( ) {
err := DestroyTest ( )
if err != nil {
t . Fatal ( err )
}
} ( )
analysisQueue := index . NewAnalysisQueue ( 1 )
idx , err := NewSmolderingCouch ( boltdb . Name , boltTestConfig , analysisQueue )
if err != nil {
t . Fatal ( err )
}
err = idx . Open ( )
if err != nil {
t . Errorf ( "error opening index: %v" , err )
}
defer func ( ) {
err := idx . Close ( )
if err != nil {
t . Fatal ( err )
}
} ( )
doc := document . NewDocument ( "1" )
doc . AddField ( document . NewTextFieldWithIndexingOptions ( "name" , [ ] uint64 { } , [ ] byte ( "test" ) , document . IndexField | document . StoreField | document . IncludeTermVectors ) )
doc . AddField ( document . NewTextFieldWithIndexingOptions ( "title" , [ ] uint64 { } , [ ] byte ( "mister" ) , document . IndexField | document . StoreField | document . IncludeTermVectors ) )
doc . AddField ( document . NewCompositeFieldWithIndexingOptions ( "_all" , true , nil , nil , document . IndexField | document . IncludeTermVectors ) )
err = idx . Update ( doc )
if err != nil {
t . Errorf ( "Error updating index: %v" , err )
}
indexReader , err := idx . Reader ( )
if err != nil {
t . Error ( err )
}
defer func ( ) {
err := indexReader . Close ( )
if err != nil {
t . Fatal ( err )
}
} ( )
termFieldReader , err := indexReader . TermFieldReader ( [ ] byte ( "mister" ) , "_all" , true , true , true )
if err != nil {
t . Error ( err )
}
tfd , err := termFieldReader . Next ( nil )
for tfd != nil && err == nil {
if ! tfd . ID . Equals ( EncodeUvarintAscending ( nil , 1 ) ) {
t . Errorf ( "expected to find document id 1" )
}
tfd , err = termFieldReader . Next ( nil )
}
if err != nil {
t . Error ( err )
}
}
func TestIndexDocumentFieldTerms ( t * testing . T ) {
defer func ( ) {
err := DestroyTest ( )
if err != nil {
t . Fatal ( err )
}
} ( )
analysisQueue := index . NewAnalysisQueue ( 1 )
idx , err := NewSmolderingCouch ( boltdb . Name , boltTestConfig , analysisQueue )
if err != nil {
t . Fatal ( err )
}
err = idx . Open ( )
if err != nil {
t . Errorf ( "error opening index: %v" , err )
}
defer func ( ) {
err := idx . Close ( )
if err != nil {
t . Fatal ( err )
}
} ( )
doc := document . NewDocument ( "1" )
doc . AddField ( document . NewTextFieldWithIndexingOptions ( "name" , [ ] uint64 { } , [ ] byte ( "test" ) , document . IndexField | document . StoreField | document . IncludeTermVectors ) )
doc . AddField ( document . NewTextFieldWithIndexingOptions ( "title" , [ ] uint64 { } , [ ] byte ( "mister" ) , document . IndexField | document . StoreField | document . IncludeTermVectors ) )
err = idx . Update ( doc )
if err != nil {
t . Errorf ( "Error updating index: %v" , err )
}
indexReader , err := idx . Reader ( )
if err != nil {
t . Error ( err )
}
defer func ( ) {
err := indexReader . Close ( )
if err != nil {
t . Fatal ( err )
}
} ( )
2016-09-09 20:11:28 +02:00
fieldTerms , err := indexReader . DocumentFieldTerms ( EncodeUvarintAscending ( nil , 1 ) , [ ] string { "_id" , "name" , "title" } )
2016-08-20 20:03:46 +02:00
if err != nil {
t . Error ( err )
}
expectedFieldTerms := index . FieldTerms {
"name" : [ ] string { "test" } ,
"title" : [ ] string { "mister" } ,
"_id" : [ ] string { "1" } ,
}
if ! reflect . DeepEqual ( fieldTerms , expectedFieldTerms ) {
t . Errorf ( "expected field terms: %#v, got: %#v" , expectedFieldTerms , fieldTerms )
}
}
func BenchmarkBatch ( b * testing . B ) {
cache := registry . NewCache ( )
analyzer , err := cache . AnalyzerNamed ( standard_analyzer . Name )
if err != nil {
b . Fatal ( err )
}
analysisQueue := index . NewAnalysisQueue ( 1 )
idx , err := NewSmolderingCouch ( null . Name , nil , analysisQueue )
if err != nil {
b . Fatal ( err )
}
err = idx . Open ( )
if err != nil {
b . Fatal ( err )
}
batch := index . NewBatch ( )
for i := 0 ; i < 100 ; i ++ {
d := document . NewDocument ( strconv . Itoa ( i ) )
f := document . NewTextFieldWithAnalyzer ( "desc" , nil , bleveWikiArticle1K , analyzer )
d . AddField ( f )
batch . Update ( d )
}
b . ResetTimer ( )
for i := 0 ; i < b . N ; i ++ {
err = idx . Batch ( batch )
if err != nil {
b . Fatal ( err )
}
}
}
func TestConcurrentUpdate ( t * testing . T ) {
defer func ( ) {
err := DestroyTest ( )
if err != nil {
t . Fatal ( err )
}
} ( )
analysisQueue := index . NewAnalysisQueue ( 1 )
idx , err := NewSmolderingCouch ( boltdb . Name , boltTestConfig , analysisQueue )
if err != nil {
t . Fatal ( err )
}
err = idx . Open ( )
if err != nil {
t . Errorf ( "error opening index: %v" , err )
}
defer func ( ) {
err := idx . Close ( )
if err != nil {
t . Fatal ( err )
}
} ( )
// do some concurrent updates
var wg sync . WaitGroup
for i := 0 ; i < 10 ; i ++ {
wg . Add ( 1 )
go func ( i int ) {
doc := document . NewDocument ( "1" )
doc . AddField ( document . NewTextFieldWithIndexingOptions ( strconv . Itoa ( i ) , [ ] uint64 { } , [ ] byte ( strconv . Itoa ( i ) ) , document . StoreField ) )
err := idx . Update ( doc )
if err != nil {
t . Errorf ( "Error updating index: %v" , err )
}
wg . Done ( )
} ( i )
}
wg . Wait ( )
// now load the name field and see what we get
r , err := idx . Reader ( )
if err != nil {
log . Fatal ( err )
}
doc , err := r . Document ( "1" )
if err != nil {
log . Fatal ( err )
}
2016-09-09 17:04:11 +02:00
if len ( doc . Fields ) > 2 {
t . Errorf ( "expected two fields, found %d" , len ( doc . Fields ) )
2016-08-20 20:03:46 +02:00
}
}
func TestLargeField ( t * testing . T ) {
defer func ( ) {
err := DestroyTest ( )
if err != nil {
t . Fatal ( err )
}
} ( )
analysisQueue := index . NewAnalysisQueue ( 1 )
idx , err := NewSmolderingCouch ( boltdb . Name , boltTestConfig , analysisQueue )
if err != nil {
t . Fatal ( err )
}
err = idx . Open ( )
if err != nil {
t . Errorf ( "error opening index: %v" , err )
}
defer func ( ) {
err := idx . Close ( )
if err != nil {
t . Fatal ( err )
}
} ( )
2016-09-13 18:40:01 +02:00
var largeFieldValue [ ] byte
2016-08-20 20:03:46 +02:00
for len ( largeFieldValue ) < RowBufferSize {
largeFieldValue = append ( largeFieldValue , bleveWikiArticle1K ... )
}
t . Logf ( "large field size: %d" , len ( largeFieldValue ) )
d := document . NewDocument ( "large" )
f := document . NewTextFieldWithIndexingOptions ( "desc" , nil , largeFieldValue , document . IndexField | document . StoreField )
d . AddField ( f )
err = idx . Update ( d )
if err != nil {
t . Fatal ( err )
}
}