Skip to content

Commit

Permalink
Merge pull request #17 from cabify/mariorvinas/add-bulk-docs
Browse files Browse the repository at this point in the history
Add bulk method
  • Loading branch information
Mario authored Aug 3, 2020
2 parents 1f50935 + eb002c8 commit 7a5349e
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 12 deletions.
28 changes: 24 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,37 @@
# Cabify CouchDB Library ChangeLog

## 0.3.1
## [Unreleased]
### Added
- BulkDocs method

### Changed
- Nothing

### Deprecated
- Nothing

### Removed
- Nothing

### Fixed
- Nothing

### Security
- Nothing

## [0.3.1] - 2020-02-13
### Fixed
- PostView func needs body and query parameters

## 0.3.0
## [0.3.0] - 2020-02-12
### Added
- PostView method to query views with POST method

## 0.2.0
## [0.2.0] - 2020-07-09
### Added
- BulkGet method to query multiple documents per id at once
- go.mod file

## 0.1.0
## [0.1.0] - 2020-06-19
### Added
- First release to be compatible with go modules
3 changes: 2 additions & 1 deletion attachments_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import (
"bytes"
"encoding/base64"
"encoding/json"
"github.com/cabify/go-couchdb"
"io"
"io/ioutil"
. "net/http"
"testing"

"github.com/cabify/go-couchdb"
)

var (
Expand Down
3 changes: 2 additions & 1 deletion auth_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package couchdb_test

import (
"github.com/cabify/go-couchdb"
"net/http"
"testing"

"github.com/cabify/go-couchdb"
)

func TestBasicAuth(t *testing.T) {
Expand Down
18 changes: 15 additions & 3 deletions bulk.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ type BulkGet struct {
Docs []struct{ ID string } `json:"docs"`
}

type BulkDocsReq struct {
Docs []interface{} `json:"docs"`
}

type errorWrapper struct {
ID string `json:"id"`
Rev string `json:"rev"`
Expand All @@ -22,11 +26,19 @@ type docWrapper struct {
Error *errorWrapper `json:"error"`
}

type bulkRes struct {
type bulkGetRes struct {
Id string `json:"id"`
Docs []docWrapper `json:"docs"`
}

type bulkResp struct {
Results []bulkRes
type bulkGetResp struct {
Results []bulkGetRes
}

type BulkDocsResp struct {
OK bool `json:"ok,omitempty"`
ID string `json:"id"`
Rev string `json:"rev,omitempty"`
Error string `json:"error,omitempty"`
Reason string `json:"reason,omitempty"`
}
66 changes: 66 additions & 0 deletions client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
Expand Down Expand Up @@ -318,6 +319,71 @@ func TestPut(t *testing.T) {
check(t, "returned rev", "1-619db7ba8551c0de3f3a178775509611", rev)
}

func TestBulkDocs(t *testing.T) {
c := newTestClient(t)
c.Handle("POST /db/_bulk_docs", func(rw http.ResponseWriter, req *http.Request) {
body, _ := ioutil.ReadAll(req.Body)
fmt.Println(string(body))
reqData := couchdb.BulkDocsReq{}
err := json.Unmarshal(body, &reqData)
check(t, "json.Unmarshal", err, nil)

check(t, "request body", "Barney", reqData.Docs[0].(map[string]interface{})["_id"])
check(t, "request body", "Fred Flintstone", reqData.Docs[1].(map[string]interface{})["name"])
check(t, "request body", "Pebbles", reqData.Docs[2].(map[string]interface{})["_id"])
check(t, "request body", "Dino", reqData.Docs[3].(map[string]interface{})["name"])

rw.WriteHeader(http.StatusOK)
_, err = io.WriteString(rw, `[{"ok":true,"id":"Barney","rev":"1"},
{"ok":true,"id":"Fred","rev":"1"},
{"ok":true,"id":"Pebbles","rev":"2"},
{"id":"Dino","error":"conflict","reason":"Document update conflict"}]`)
check(t, "io.WriteString", err, nil)

})

type createDoc struct {
Name string `json:"name"`
ID string `json:"_id"`
Rev string `json:"_rev"`
}
type updateDoc struct {
Name string `json:"name"`
Age int32 `json:"age"`
}
type delDoc struct {
ID string `json:"_id"`
Rev string `json:"_rev"`
Deleted bool `json:"_deleted"`
}

docCreate := &createDoc{"Barney Rubble", "Barney", "1"}
docUpdate := &updateDoc{"Fred Flintstone", 41}
docDel := &delDoc{"Pebbles", "2", true}
docFailUpdate := &updateDoc{Name: "Dino", Age: 5}

res, err := c.DB("db").BulkDocs(docCreate, docUpdate, docDel, docFailUpdate)
check(t, "BulkDocs", err, nil)

createRes := res[0]
check(t, "createRes.OK", true, createRes.OK)
check(t, "createRes.ID", "Barney", createRes.ID)
check(t, "createRes.Rev", "1", createRes.Rev)

updateRes := res[1]
check(t, "updateRes.OK", true, updateRes.OK)

delRes := res[2]
check(t, "delRes.OK", true, delRes.OK)
check(t, "delRes.ID", "Pebbles", delRes.ID)
check(t, "delRes.Rev", "2", delRes.Rev)

updateFailuteRes := res[3]
check(t, "updateFailuteRes.OK", false, updateFailuteRes.OK)
check(t, "updateFailuteRes.ID", "Dino", updateFailuteRes.ID)
check(t, "updateFailuteRes.Error", "conflict", updateFailuteRes.Error)
}

func TestPutWithRev(t *testing.T) {
c := newTestClient(t)
c.Handle("PUT /db/doc", func(resp http.ResponseWriter, req *http.Request) {
Expand Down
3 changes: 2 additions & 1 deletion couchapp/couchapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ import (
"bytes"
"encoding/json"
"fmt"
"github.com/cabify/go-couchdb"
"io/ioutil"
"mime"
"os"
"path"
"strings"

"github.com/cabify/go-couchdb"
)

// DefaultIgnorePatterns contains the default list of glob patterns
Expand Down
45 changes: 44 additions & 1 deletion db.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"bytes"
"context"
"encoding/json"
"net/http"
"reflect"
"strings"
)
Expand Down Expand Up @@ -85,7 +86,7 @@ func (db *DB) BulkGet(ids []string, docType interface{}, opts Options) (docs []i
return nil, nil, err
}

response := bulkResp{}
response := bulkGetResp{}
err = readBody(resp, &response)
if err != nil {
return nil, nil, err
Expand Down Expand Up @@ -149,6 +150,48 @@ func (db *DB) Put(id string, doc interface{}, rev string) (newrev string, err er
return responseRev(db.closedRequest(db.ctx, "PUT", path, b))
}

// BulkDocs allows to create, update and/or delete multiple documents in a single request.
// The basic operations are similar to creating or updating a single document,
// except that they are batched into one request.
//
// BulkDocs accepts an array of documents to be processed.
// Documents may contain _id, _rev and _deleted,
// depending on the wanted operation,
// as well as the corresponding document fields if needed.
//
// It returns a slice of results with the outcome of every operation or an error.
// The only mandatory field is the ID.
// The rest of the structure of the result depends if it was successful or not.
// Note that no error will be returned if an operation or more fail.
//
// Observe that behaviour of two or more operations in a single document is undetermined.
// There are no guarantees that the operations will be processed in any given order.
//
// Reference: https://cloud.ibm.com/docs/Cloudant?topic=Cloudant-documents#bulk-operations
func (db *DB) BulkDocs(docs ...interface{}) (res []BulkDocsResp, err error) {
path := revpath("", db.name, "_bulk_docs")

var req BulkDocsReq
req.Docs = make([]interface{}, 0, len(docs))
for _, doc := range docs {
req.Docs = append(req.Docs, doc)
}

bodyJSON, err := json.Marshal(req)
if err != nil {
return nil, err
}
body := bytes.NewReader(bodyJSON)
httpResp, err := db.request(db.ctx, http.MethodPost, path, body)

err = readBody(httpResp, &res)
if err != nil {
return nil, err
}

return res, nil
}

// Delete marks a document revision as deleted.
func (db *DB) Delete(id, rev string) (newrev string, err error) {
path := revpath(rev, db.name, id)
Expand Down
3 changes: 2 additions & 1 deletion x_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ package couchdb_test

import (
"bytes"
"github.com/cabify/go-couchdb"
"io/ioutil"
"net/http"
"net/http/httptest"
"reflect"
"testing"

"github.com/cabify/go-couchdb"
)

// testClient is a very special couchdb.Client that also implements
Expand Down

0 comments on commit 7a5349e

Please sign in to comment.