Merge pull request #14 from acasas/fields_struct

Support for passing a struct to a document instead of map[string]interface{}
This commit is contained in:
Jérôme Renard 2014-08-18 08:28:09 +02:00
commit 7e772ee99b
4 changed files with 129 additions and 26 deletions

View File

@ -8,13 +8,35 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"net/url" "net/url"
"os"
"time" "time"
"github.com/belogik/goes" "github.com/belogik/goes"
) )
var (
ES_HOST = "localhost"
ES_PORT = "9200"
)
func getConnection() (conn *goes.Connection) {
h := os.Getenv("TEST_ELASTICSEARCH_HOST")
if h == "" {
h = ES_HOST
}
p := os.Getenv("TEST_ELASTICSEARCH_PORT")
if p == "" {
p = ES_PORT
}
conn = goes.NewConnection(h, p)
return
}
func ExampleConnection_CreateIndex() { func ExampleConnection_CreateIndex() {
conn := goes.NewConnection("localhost", "9200") conn := getConnection()
mapping := map[string]interface{}{ mapping := map[string]interface{}{
"settings": map[string]interface{}{ "settings": map[string]interface{}{
@ -43,7 +65,7 @@ func ExampleConnection_CreateIndex() {
} }
func ExampleConnection_DeleteIndex() { func ExampleConnection_DeleteIndex() {
conn := goes.NewConnection("localhost", "9200") conn := getConnection()
resp, err := conn.DeleteIndex("yourinde") resp, err := conn.DeleteIndex("yourinde")
if err != nil { if err != nil {
@ -54,7 +76,7 @@ func ExampleConnection_DeleteIndex() {
} }
func ExampleConnection_RefreshIndex() { func ExampleConnection_RefreshIndex() {
conn := goes.NewConnection("localhost", "9200") conn := getConnection()
resp, err := conn.RefreshIndex("yourindex") resp, err := conn.RefreshIndex("yourindex")
if err != nil { if err != nil {
@ -65,7 +87,7 @@ func ExampleConnection_RefreshIndex() {
} }
func ExampleConnection_Search() { func ExampleConnection_Search() {
conn := goes.NewConnection("localhost", "9200") conn := getConnection()
var query = map[string]interface{}{ var query = map[string]interface{}{
"query": map[string]interface{}{ "query": map[string]interface{}{
@ -102,7 +124,7 @@ func ExampleConnection_Search() {
} }
func ExampleConnection_Index() { func ExampleConnection_Index() {
conn := goes.NewConnection("localhost", "9200") conn := getConnection()
d := goes.Document{ d := goes.Document{
Index: "twitter", Index: "twitter",
@ -126,7 +148,7 @@ func ExampleConnection_Index() {
} }
func ExampleConnection_Delete() { func ExampleConnection_Delete() {
conn := goes.NewConnection("localhost", "9200") conn := getConnection()
//[create index, index document ...] //[create index, index document ...]
@ -154,7 +176,8 @@ func ExampleConnectionOverrideHttpClient() {
cl := &http.Client{ cl := &http.Client{
Transport: tr, Transport: tr,
} }
conn := goes.NewConnection("localhost", "9200").WithClient(cl) conn := getConnection()
conn.WithClient(cl)
fmt.Printf("%v\n", conn.Client) fmt.Printf("%v\n", conn.Client)
} }

23
goes.go
View File

@ -13,6 +13,7 @@ import (
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"net/url" "net/url"
"reflect"
"strconv" "strconv"
"strings" "strings"
) )
@ -139,13 +140,25 @@ func (c *Connection) BulkSend(documents []Document) (Response, error) {
bulkData[i] = action bulkData[i] = action
i++ i++
if len(doc.Fields) > 0 { if doc.Fields != nil {
fields := make(map[string]interface{}, len(doc.Fields)) if docFields, ok := doc.Fields.(map[string]interface{}); ok {
for fieldName, fieldValue := range doc.Fields { if len(docFields) == 0 {
fields[fieldName] = fieldValue continue
}
} else {
typeOfFields := reflect.TypeOf(doc.Fields)
if typeOfFields.Kind() == reflect.Ptr {
typeOfFields = typeOfFields.Elem()
}
if typeOfFields.Kind() != reflect.Struct {
return Response{}, fmt.Errorf("Document fields not in struct or map[string]interface{} format")
}
if typeOfFields.NumField() == 0 {
continue
}
} }
sources, err := json.Marshal(fields) sources, err := json.Marshal(doc.Fields)
if err != nil { if err != nil {
return Response{}, err return Response{}, err
} }

View File

@ -193,7 +193,7 @@ func (s *GoesTestSuite) TestBulkSend(c *C) {
docType := "tweet" docType := "tweet"
tweets := []Document{ tweets := []Document{
Document{ {
Id: "123", Id: "123",
Index: indexName, Index: indexName,
Type: docType, Type: docType,
@ -204,7 +204,7 @@ func (s *GoesTestSuite) TestBulkSend(c *C) {
}, },
}, },
Document{ {
Id: nil, Id: nil,
Index: indexName, Index: indexName,
Type: docType, Type: docType,
@ -263,13 +263,13 @@ func (s *GoesTestSuite) TestBulkSend(c *C) {
c.Assert(checked, Equals, 2) c.Assert(checked, Equals, 2)
docToDelete := []Document{ docToDelete := []Document{
Document{ {
Id: "123", Id: "123",
Index: indexName, Index: indexName,
Type: docType, Type: docType,
BulkCommand: BULK_COMMAND_DELETE, BulkCommand: BULK_COMMAND_DELETE,
}, },
Document{ {
Id: extraDocId, Id: extraDocId,
Index: indexName, Index: indexName,
Type: docType, Type: docType,
@ -321,6 +321,73 @@ func (s *GoesTestSuite) TestStats(c *C) {
c.Assert(err, IsNil) c.Assert(err, IsNil)
} }
func (s *GoesTestSuite) TestIndexWithFieldsInStruct(c *C) {
indexName := "testindexwithfieldsinstruct"
docType := "tweet"
docId := "1234"
conn := NewConnection(ES_HOST, ES_PORT)
// just in case
conn.DeleteIndex(indexName)
_, err := conn.CreateIndex(indexName, map[string]interface{}{})
c.Assert(err, IsNil)
defer conn.DeleteIndex(indexName)
d := Document{
Index: indexName,
Type: docType,
Id: docId,
Fields: struct {
user string
message string
}{
"foo",
"bar",
},
}
extraArgs := make(url.Values, 1)
extraArgs.Set("ttl", "86400000")
response, err := conn.Index(d, extraArgs)
c.Assert(err, IsNil)
expectedResponse := Response{
Index: indexName,
Id: docId,
Type: docType,
Version: 1,
}
c.Assert(response, DeepEquals, expectedResponse)
}
func (s *GoesTestSuite) TestIndexWithFieldsNotInMapOrStruct(c *C) {
indexName := "testindexwithfieldsnotinmaporstruct"
docType := "tweet"
docId := "1234"
conn := NewConnection(ES_HOST, ES_PORT)
// just in case
conn.DeleteIndex(indexName)
_, err := conn.CreateIndex(indexName, map[string]interface{}{})
c.Assert(err, IsNil)
defer conn.DeleteIndex(indexName)
d := Document{
Index: indexName,
Type: docType,
Id: docId,
Fields: "test",
}
extraArgs := make(url.Values, 1)
extraArgs.Set("ttl", "86400000")
_, err = conn.Index(d, extraArgs)
c.Assert(err, Not(IsNil))
}
func (s *GoesTestSuite) TestIndexIdDefined(c *C) { func (s *GoesTestSuite) TestIndexIdDefined(c *C) {
indexName := "testindexiddefined" indexName := "testindexiddefined"
docType := "tweet" docType := "tweet"
@ -534,7 +601,7 @@ func (s *GoesTestSuite) TestSearch(c *C) {
"query": map[string]interface{}{ "query": map[string]interface{}{
"bool": map[string]interface{}{ "bool": map[string]interface{}{
"must": []map[string]interface{}{ "must": []map[string]interface{}{
map[string]interface{}{ {
"match_all": map[string]interface{}{}, "match_all": map[string]interface{}{},
}, },
}, },
@ -547,7 +614,7 @@ func (s *GoesTestSuite) TestSearch(c *C) {
Total: 1, Total: 1,
MaxScore: 1.0, MaxScore: 1.0,
Hits: []Hit{ Hits: []Hit{
Hit{ {
Index: indexName, Index: indexName,
Type: docType, Type: docType,
Id: docId, Id: docId,
@ -592,7 +659,7 @@ func (s *GoesTestSuite) TestIndexStatus(c *C) {
c.Assert(sizeInBytes > 0, Equals, true) c.Assert(sizeInBytes > 0, Equals, true)
expectedIndices := map[string]IndexStatus{ expectedIndices := map[string]IndexStatus{
indexName: IndexStatus{ indexName: {
Index: map[string]interface{}{ Index: map[string]interface{}{
"primary_size_in_bytes": primarySizeInBytes, "primary_size_in_bytes": primarySizeInBytes,
"size_in_bytes": sizeInBytes, "size_in_bytes": sizeInBytes,
@ -633,7 +700,7 @@ func (s *GoesTestSuite) TestScroll(c *C) {
docType := "tweet" docType := "tweet"
tweets := []Document{ tweets := []Document{
Document{ {
Id: nil, Id: nil,
Index: indexName, Index: indexName,
Type: docType, Type: docType,
@ -644,7 +711,7 @@ func (s *GoesTestSuite) TestScroll(c *C) {
}, },
}, },
Document{ {
Id: nil, Id: nil,
Index: indexName, Index: indexName,
Type: docType, Type: docType,
@ -655,7 +722,7 @@ func (s *GoesTestSuite) TestScroll(c *C) {
}, },
}, },
Document{ {
Id: nil, Id: nil,
Index: indexName, Index: indexName,
Type: docType, Type: docType,
@ -733,7 +800,7 @@ func (s *GoesTestSuite) TestAggregations(c *C) {
docType := "tweet" docType := "tweet"
tweets := []Document{ tweets := []Document{
Document{ {
Id: nil, Id: nil,
Index: indexName, Index: indexName,
Type: docType, Type: docType,
@ -745,7 +812,7 @@ func (s *GoesTestSuite) TestAggregations(c *C) {
}, },
}, },
Document{ {
Id: nil, Id: nil,
Index: indexName, Index: indexName,
Type: docType, Type: docType,
@ -757,7 +824,7 @@ func (s *GoesTestSuite) TestAggregations(c *C) {
}, },
}, },
Document{ {
Id: nil, Id: nil,
Index: indexName, Index: indexName,
Type: docType, Type: docType,

View File

@ -102,7 +102,7 @@ type Document struct {
Type string Type string
Id interface{} Id interface{}
BulkCommand string BulkCommand string
Fields map[string]interface{} Fields interface{}
} }
// Represents the "items" field in a _bulk response // Represents the "items" field in a _bulk response