Allow multiple inputs to Indexer's AddDoc.
* Doc object
* Go struct
* map[string]interface{}
Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/2bec52c1
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/2bec52c1
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/2bec52c1
Branch: refs/heads/master
Commit: 2bec52c1c8314c68a0687b09a088406ddce3211c
Parents: 8223307
Author: Marvin Humphrey <[email protected]>
Authored: Fri Sep 18 18:59:27 2015 -0700
Committer: Marvin Humphrey <[email protected]>
Committed: Mon Sep 28 12:54:38 2015 -0700
----------------------------------------------------------------------
go/lucy/index.go | 80 ++++++++++++++++++++++++++++++++++------------
go/lucy/index_test.go | 39 ++++++++++++++++++++++
2 files changed, 99 insertions(+), 20 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy/blob/2bec52c1/go/lucy/index.go
----------------------------------------------------------------------
diff --git a/go/lucy/index.go b/go/lucy/index.go
index 1662d3e..0ec4c97 100644
--- a/go/lucy/index.go
+++ b/go/lucy/index.go
@@ -70,55 +70,95 @@ func (obj *IndexerIMP) Close() error {
return nil // TODO catch errors
}
-func (obj *IndexerIMP) AddDoc(doc interface{}) error {
- self := ((*C.lucy_Indexer)(unsafe.Pointer(obj.TOPTR())))
- stockDoc := C.LUCY_Indexer_Get_Stock_Doc(self)
- docFields := fetchDocFields(stockDoc)
+func (obj *IndexerIMP) addDocObj(doc Doc, boost float32) error {
+ self := (*C.lucy_Indexer)(clownfish.Unwrap(obj, "obj"))
+ d := (*C.lucy_Doc)(clownfish.Unwrap(doc, "doc"))
+ return clownfish.TrapErr(func() {
+ C.LUCY_Indexer_Add_Doc(self, d, C.float(boost))
+ })
+}
+
+func (obj *IndexerIMP) addMapAsDoc(doc map[string]interface{}, boost float32)
error {
+ self := (*C.lucy_Indexer)(clownfish.Unwrap(obj, "obj"))
+ d := C.LUCY_Indexer_Get_Stock_Doc(self)
+ docFields := fetchDocFields(d)
for field := range docFields {
delete(docFields, field)
}
+ for key, value := range doc {
+ field, err := obj.findRealField(key)
+ if err != nil {
+ return err
+ }
+ docFields[field] = value
+ }
+ return clownfish.TrapErr(func() {
+ C.LUCY_Indexer_Add_Doc(self, d, C.float(boost))
+ })
+}
- // TODO: Support map as doc in addition to struct as doc.
+func (obj *IndexerIMP) addStructAsDoc(doc interface{}, boost float32) error {
+ self := (*C.lucy_Indexer)(clownfish.Unwrap(obj, "obj"))
+ d := C.LUCY_Indexer_Get_Stock_Doc(self)
+ docFields := fetchDocFields(d)
+ for field := range docFields {
+ delete(docFields, field)
+ }
// Get reflection value and type for the supplied struct.
var docValue reflect.Value
+ var success bool
if reflect.ValueOf(doc).Kind() == reflect.Ptr {
temp := reflect.ValueOf(doc).Elem()
if temp.Kind() == reflect.Struct {
docValue = temp
+ success = true
}
}
- if docValue == (reflect.Value{}) {
- mess := fmt.Sprintf("Doc not struct pointer: %v",
- reflect.TypeOf(doc))
+ if !success {
+ mess := fmt.Sprintf("Unexpected type for doc: %t", doc)
return clownfish.NewErr(mess)
}
- docType := docValue.Type()
+ // Copy field values into stockDoc.
+ docType := docValue.Type()
for i := 0; i < docValue.NumField(); i++ {
field := docType.Field(i).Name
value := docValue.Field(i).String()
- realField := obj.findRealField(field)
+ realField, err := obj.findRealField(field)
+ if err != nil {
+ return err
+ }
docFields[realField] = value
}
+ return clownfish.TrapErr(func() {
+ C.LUCY_Indexer_Add_Doc(self, d, C.float(boost))
+ })
+}
+
+func (obj *IndexerIMP) AddDoc(doc interface{}) error {
// TODO create an additional method AddDocWithBoost which allows the
// client to supply `boost`.
- boost := 1.0
- err := clownfish.TrapErr(func() {
- C.LUCY_Indexer_Add_Doc(self, stockDoc, C.float(boost))
- })
+ boost := float32(1.0)
- return err
+ if suppliedDoc, ok := doc.(Doc); ok {
+ return obj.addDocObj(suppliedDoc, boost)
+ } else if m, ok := doc.(map[string]interface{}); ok {
+ return obj.addMapAsDoc(m, boost)
+ } else {
+ return obj.addStructAsDoc(doc, boost)
+ }
}
-func (obj *IndexerIMP) findRealField(name string) string {
+func (obj *IndexerIMP) findRealField(name string) (string, error) {
self := ((*C.lucy_Indexer)(unsafe.Pointer(obj.TOPTR())))
if obj.fieldNames == nil {
obj.fieldNames = make(map[string]string)
}
- f, ok := obj.fieldNames[name]
- if !ok {
+ if field, ok := obj.fieldNames[name]; ok {
+ return field, nil
+ } else {
schema := C.LUCY_Indexer_Get_Schema(self)
fieldList := C.LUCY_Schema_All_Fields(schema)
defer C.cfish_dec_refcount(unsafe.Pointer(fieldList))
@@ -126,12 +166,12 @@ func (obj *IndexerIMP) findRealField(name string) string {
cfString := unsafe.Pointer(C.CFISH_Vec_Fetch(fieldList,
C.size_t(i)))
field := clownfish.CFStringToGo(cfString)
if strings.EqualFold(name, field) {
- f = field
obj.fieldNames[name] = field
+ return field, nil
}
}
}
- return f
+ return "", clownfish.NewErr(fmt.Sprintf("Unknown field: '%v'", name))
}
func (obj *IndexerIMP) Commit() error {
http://git-wip-us.apache.org/repos/asf/lucy/blob/2bec52c1/go/lucy/index_test.go
----------------------------------------------------------------------
diff --git a/go/lucy/index_test.go b/go/lucy/index_test.go
new file mode 100644
index 0000000..5967a31
--- /dev/null
+++ b/go/lucy/index_test.go
@@ -0,0 +1,39 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 lucy
+
+import "testing"
+
+func TestIndexerAddDoc(t *testing.T) {
+ schema := createTestSchema()
+ index := NewRAMFolder("")
+ indexer, _ := OpenIndexer(&OpenIndexerArgs{
+ Create: true,
+ Index: index,
+ Schema: schema,
+ })
+ indexer.AddDoc(&testDoc{Content: "foo"})
+ indexer.AddDoc(map[string]interface{}{"content": "foo"})
+ doc := NewDoc(0)
+ doc.Store("content", "foo")
+ indexer.AddDoc(doc)
+ indexer.Commit()
+ searcher, _ := OpenIndexSearcher(index)
+ if got := searcher.DocFreq("content", "foo"); got != 3 {
+ t.Errorf("Didn't index all docs -- DocMax: %d", got)
+ }
+}