A Cloudant library for Golang.
Forked from cloudant-labs and modified to align closer to NodeJS nano
library. This library is not complete, may change in incompatible ways in future versions, and comes with no support. Please consider using the official Cloudant GO SDK
Features:
- Session authentication
- Keep-Alive & Connection Pooling
- Configurable request retrying
- Hard limit on request concurrency
- Stream
/_changes
,/_all_docs
, and other views - Manage
/_bulk_docs
uploads - Convenient query helpers
- Support for views and raw JSON
- Convenient (optional)
cloudanti
interface and mock package - Set of examples with or without using the interface
go get github.com/barshociaj/go-cloudant
// Create a Cloudant client with default configuration:
// - concurrency: 5
// - maximum retries per request: 3
// - random retry delay minimum: 5 seconds
// - random retry delay maximum: 30 seconds
client, err := cloudant.NewClient("user123", "pa55w0rd01", "https://user123.cloudant.com")
// OR provide any number of custom client options
//
// client, err := cloudant.NewClient("user123", "pa55w0rd01", "https://user123.cloudant.com", cloudant.ClientConcurrency(20), cloudant.ClientRetryCountMax(5), cloudant.ClientRetryDelayMin(10), cloudant.ClientRetryDelayMax(60))
Delete existing database
err := client.Destroy("my_db")
Checks if database exists
exists, err := client.Exists("my_db")
Retrieve database info
info, err := client.Info("my_db")
fmt.Println(info.DocCount) // prints the number of documents in the database
List existing databases
dbList, err := client.List(cloudant.NewDBsQuery())
for _, name := range *dbList {
fmt.Println(name) // prints database names
}
Use existing database:
db, err := client.Use("my_database")
Create (if does not exist) and use a database:
db, err := client.UseOrCreate("my_database")
Get changes feed from the database
q := cloudant.NewChangesQuery().IncludeDocs()
changes, err := db.Changes(q)
for {
change, more := <-changes
if more {
fmt.Println(change.Seq, change.Id, change.Rev) // prints change 'seq', 'id' and 'rev'
// Doc body
str, _ := json.MarshalIndent(change.Doc, "", " ")
fmt.Printf("%s\n", str)
} else {
break
}
}
Creates a new changes feed follower that runs in continuous mode, emitting
events from the changes feed on a channel. Its aims is to stay running until told to
terminate with changes.Close()
// Only generate a Seq ID every 100 changes
follower := db.NewFollower(100)
changes, err := follower.Follow()
if err != nil {
fmt.Println(err)
return
}
for {
changeEvent := <-changes
switch changeEvent.EventType {
case cloudant.ChangesHeartbeat:
fmt.Println("tick")
case cloudant.ChangesError:
fmt.Println(changeEvent.Err)
case cloudant.ChangesTerminated:
fmt.Println("terminated; resuming from last known sequence id")
changes, err = follower.Follow()
if err != nil {
fmt.Println("resumption error ", err)
return
}
case cloudant.ChangesInsert:
fmt.Printf("INSERT %s\n", changeEvent.Meta.ID)
case cloudant.ChangesDelete:
fmt.Printf("DELETE %s\n", changeEvent.Meta.ID)
default:
fmt.Printf("UPDATE %s\n", changeEvent.Meta.ID)
}
}
Removes a document from database
err := db.Destroy("my_doc_id", "2-xxxxxxx")
Gets a document from Cloudant whose _id is docID and unmarshals it into doc struct
type Doc struct {
Id string `json:"_id"`
Rev string `json:"_rev"`
Foo string `json:"foo"`
}
doc = new(Doc)
err = db.Get("my_doc_id", cloudant.NewDocQuery(), doc)
fmt.Println(doc.Foo) // prints 'foo' key
Inserts doc
in the database
myDoc := &Doc{
ID: "my_doc_id",
Foo: "bar",
}
newRev, err := db.Insert(myDoc)
fmt.Println(newRev) // prints '_rev' of new document revision
Inserts myDoc
in the database and escapes HTML in strings
newRev, err := db.InsertEscaped(myDoc)
Inserts raw JSON ([]byte) in the database
json := []byte(`{
"_id": "_design/test_design_doc",
"language": "javascript",
"views": {
"cities": {
"map": "function (doc) { if (doc._id.indexOf('city_') == 0) emit(doc._id, doc.foo) }"
}
}
}`)
newRev, err := db.InsertRaw(json)
Bulk operations(update/delete/insert) on the database's /_bulk_docs
endpoint
myDoc1 := Doc{
ID: "doc1",
Foo: "bar",
}
myDoc2 := Doc{
ID: "doc2",
Foo: "bar",
}
myDoc3 := Doc{
ID: "doc3",
Foo: "bar",
}
uploader := db.Bulk(50, 1048576, 60) // new uploader using batch size 50, max batch size 1MB, flushing documents to server every 60 seconds
// Note: workers only flush their document batch to the server:
// 1) periodically (set to -1 to disable).
// 2) when the maximum number of documents per batch is reached.
// 3) when the maximum batch size (in bytes) is reached (set to -1 to disable).
// 4) if a document is uploaded using `.UploadNow(doc)`.
// 5) if a client calls `.Flush()` or `.Stop()`.
uploader.FireAndForget(myDoc1)
upload.Flush() // blocks until all received documents have been uploaded
r2 := uploader.UploadNow(myDoc2) // uploaded as soon as it's received by a worker
r2.Wait()
if r2.Error != nil {
fmt.Println(r2.Response.Id, r2.Response.Rev) // prints new document '_id' and 'rev'
}
r3 := uploader.Upload(myDoc3) // queues until the worker creates a full batch of 50 documents
upload.AsyncFlush() // asynchronously uploads all received documents
upload.Stop() // blocks until all documents have been uploaded and workers have stopped
r3.Wait()
if r3.Error != nil {
fmt.Println(r3.Response.Id, r3.Response.Rev) // prints new document '_id' and 'rev'
}
List all docs in the database (_all_docs
view) and returns each row as []byte. See db.View example if you'd like to read the document body.
type MyRow struct {
ID string `json:"id"`
Value MyRowValue `json:"value"`
}
type MyRowValue struct {
Rev string `json:"rev"`
}
rows, err := db.List(cloudant.NewViewQuery())
// OR include some query options...
//
// q := cloudant.NewViewQuery().
// Limit(123).
// StartKey("foo1").
// EndKey("foo2")
//
// rows, err := db.List(q)
for {
row, more := <-rows
if more {
r := new(MyRow)
err = json.Unmarshal(row, r)
if err == nil {
fmt.Println(r.ID, r.Value.Rev) // prints document 'id' and 'rev'
}
} else {
break
}
}
Calls the viewName of the specified designName and returns each row as []byte.
type MyRow struct {
ID string `json:"id"`
Key string `json:"key"`
Value string `json:"value"`
Doc MyDoc `json:"doc"`
}
type MyDoc struct {
ID string `json:"_id,omitempty"`
Rev string `json:"_rev,omitempty"`
Foo string `json:"foo" binding:"required"`
}
q := cloudant.NewViewQuery().
Descending().
Key("foo1").
Limit(1).
IncludeDocs()
rows, err := db.View("my_design_name", "my_view_name", q)
for {
row, more := <-rows
if more {
r := new(MyRow)
err = json.Unmarshal(row, r)
if err == nil {
fmt.Println(r.Doc.ID, r.Doc.Rev, r.Doc.Foo) // prints document 'id', 'rev', and 'foo' value
}
} else {
break
}
}
Calls the viewName of the specified designName and returns raw []byte response. This allows querying views with arbitrary output such as when using reduce.
import "github.com/buger/jsonparser"
response, err := db.ViewRaw("my_design_name", "my_view_name", cloudant.NewViewQuery())
if err != nil {
value, decodeErr := jsonparser.Get(response, "total_rows")
}
Refer to the guidance in CONTRIBUTING.