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)
+       }
+}

Reply via email to