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"
"net/http"
"net/url"
"os"
"time"
"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() {
conn := goes.NewConnection("localhost", "9200")
conn := getConnection()
mapping := map[string]interface{}{
"settings": map[string]interface{}{
@ -43,7 +65,7 @@ func ExampleConnection_CreateIndex() {
}
func ExampleConnection_DeleteIndex() {
conn := goes.NewConnection("localhost", "9200")
conn := getConnection()
resp, err := conn.DeleteIndex("yourinde")
if err != nil {
@ -54,7 +76,7 @@ func ExampleConnection_DeleteIndex() {
}
func ExampleConnection_RefreshIndex() {
conn := goes.NewConnection("localhost", "9200")
conn := getConnection()
resp, err := conn.RefreshIndex("yourindex")
if err != nil {
@ -65,7 +87,7 @@ func ExampleConnection_RefreshIndex() {
}
func ExampleConnection_Search() {
conn := goes.NewConnection("localhost", "9200")
conn := getConnection()
var query = map[string]interface{}{
"query": map[string]interface{}{
@ -102,7 +124,7 @@ func ExampleConnection_Search() {
}
func ExampleConnection_Index() {
conn := goes.NewConnection("localhost", "9200")
conn := getConnection()
d := goes.Document{
Index: "twitter",
@ -126,7 +148,7 @@ func ExampleConnection_Index() {
}
func ExampleConnection_Delete() {
conn := goes.NewConnection("localhost", "9200")
conn := getConnection()
//[create index, index document ...]
@ -154,7 +176,8 @@ func ExampleConnectionOverrideHttpClient() {
cl := &http.Client{
Transport: tr,
}
conn := goes.NewConnection("localhost", "9200").WithClient(cl)
conn := getConnection()
conn.WithClient(cl)
fmt.Printf("%v\n", conn.Client)
}

23
goes.go
View File

@ -13,6 +13,7 @@ import (
"io/ioutil"
"net/http"
"net/url"
"reflect"
"strconv"
"strings"
)
@ -139,13 +140,25 @@ func (c *Connection) BulkSend(documents []Document) (Response, error) {
bulkData[i] = action
i++
if len(doc.Fields) > 0 {
fields := make(map[string]interface{}, len(doc.Fields))
for fieldName, fieldValue := range doc.Fields {
fields[fieldName] = fieldValue
if doc.Fields != nil {
if docFields, ok := doc.Fields.(map[string]interface{}); ok {
if len(docFields) == 0 {
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 {
return Response{}, err
}

View File

@ -193,7 +193,7 @@ func (s *GoesTestSuite) TestBulkSend(c *C) {
docType := "tweet"
tweets := []Document{
Document{
{
Id: "123",
Index: indexName,
Type: docType,
@ -204,7 +204,7 @@ func (s *GoesTestSuite) TestBulkSend(c *C) {
},
},
Document{
{
Id: nil,
Index: indexName,
Type: docType,
@ -263,13 +263,13 @@ func (s *GoesTestSuite) TestBulkSend(c *C) {
c.Assert(checked, Equals, 2)
docToDelete := []Document{
Document{
{
Id: "123",
Index: indexName,
Type: docType,
BulkCommand: BULK_COMMAND_DELETE,
},
Document{
{
Id: extraDocId,
Index: indexName,
Type: docType,
@ -321,6 +321,73 @@ func (s *GoesTestSuite) TestStats(c *C) {
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) {
indexName := "testindexiddefined"
docType := "tweet"
@ -534,7 +601,7 @@ func (s *GoesTestSuite) TestSearch(c *C) {
"query": map[string]interface{}{
"bool": map[string]interface{}{
"must": []map[string]interface{}{
map[string]interface{}{
{
"match_all": map[string]interface{}{},
},
},
@ -547,7 +614,7 @@ func (s *GoesTestSuite) TestSearch(c *C) {
Total: 1,
MaxScore: 1.0,
Hits: []Hit{
Hit{
{
Index: indexName,
Type: docType,
Id: docId,
@ -592,7 +659,7 @@ func (s *GoesTestSuite) TestIndexStatus(c *C) {
c.Assert(sizeInBytes > 0, Equals, true)
expectedIndices := map[string]IndexStatus{
indexName: IndexStatus{
indexName: {
Index: map[string]interface{}{
"primary_size_in_bytes": primarySizeInBytes,
"size_in_bytes": sizeInBytes,
@ -633,7 +700,7 @@ func (s *GoesTestSuite) TestScroll(c *C) {
docType := "tweet"
tweets := []Document{
Document{
{
Id: nil,
Index: indexName,
Type: docType,
@ -644,7 +711,7 @@ func (s *GoesTestSuite) TestScroll(c *C) {
},
},
Document{
{
Id: nil,
Index: indexName,
Type: docType,
@ -655,7 +722,7 @@ func (s *GoesTestSuite) TestScroll(c *C) {
},
},
Document{
{
Id: nil,
Index: indexName,
Type: docType,
@ -733,7 +800,7 @@ func (s *GoesTestSuite) TestAggregations(c *C) {
docType := "tweet"
tweets := []Document{
Document{
{
Id: nil,
Index: indexName,
Type: docType,
@ -745,7 +812,7 @@ func (s *GoesTestSuite) TestAggregations(c *C) {
},
},
Document{
{
Id: nil,
Index: indexName,
Type: docType,
@ -757,7 +824,7 @@ func (s *GoesTestSuite) TestAggregations(c *C) {
},
},
Document{
{
Id: nil,
Index: indexName,
Type: docType,

View File

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