6

I just getting started with Couchbase in Go, using the library gocb.

Just as a proof of concept trying to query my server for a specific ID and get a result. Here is a modified code sample below.

cOpts := gocb.ClusterOptions{
        Authenticator: gocb.PasswordAuthenticator{
            Username: "user",
            Password: "pw",
        },
    }

    cluster, err := gocb.Connect("couchbase://my.dev.server.net/", cOpts)
    if err != nil {
        panic(err)
    }

    qOpts := gocb.QueryOptions{}

    // create query
    queryStr := "SELECT * FROM myBucket WHERE id = '123456789'"

    rows, err := cluster.Query(queryStr, &qOpts)
    if err != nil {
        panic(err)
    }

    fmt.Printf("rows: %v\n", rows)

    for rows.Next() {
        var intfc interface{}
        err = rows.Row(&intfc)
        if err != nil {
            panic(err)
        }
        fmt.Printf("interface result: %v\n", intfc)

    }

The couchbase server is on 5.1.

I am either getting...

panic: ambiguous timeout | {"statement":"SELECT * FROM myBucketName WHERE id = '123456789'","client_context_id":"cdd52a06-c7a5-4d3d-8r26-99fg806d559e"}

...when I run the above code.
OR If I put in the following lines after the gocb.Connect(... I get the error that is after that.

err = cluster.WaitUntilReady(25*time.Second, &gocb.WaitUntilReadyOptions{DesiredState: gocb.ClusterStateOnline})
if err != nil {
    panic(err)
}

...error...

panic: unambiguous timeout | {"InnerError":{"InnerError":{"InnerError":{},"Message":"unambiguous timeout"}},"OperationID":"WaitUntilReady","Opaque":"","TimeObserved":25000263891,"RetryReasons":["NOT_READY"],"RetryAttempts":105,"LastDispatchedTo":"","LastDispatchedFrom":"","LastConnectionID":""}  

NOTE: I changed the Username, Password, Server/connStr, bucket, and the id just for example purposes here.

What am I missing here?

Matthew Groves
  • 25,181
  • 9
  • 71
  • 121
Keith E. Truesdell
  • 552
  • 11
  • 21
  • 2
    I don't know if this is the underlying problem, but do you actually have a field named 'id' in your documents? In Couchbase, `id` is not a reserved word or special field or anything. If you actually mean to query by the document ID, you can try `SELECT * FROM myBucketName USE KEYS "123456789"` – Matthew Groves Jul 21 '22 at 20:07
  • 2
    If it's a connectivity issue, the [Couchbase SDK Doctor tool](https://docs.couchbase.com/server/current/sdk/sdk-doctor.html) might be able to help diagnose it. – dnault Jul 21 '22 at 20:18
  • 2
    Have you tried removing the trailing slash from the connection string? That is, try `"couchbase://my.dev.server.net"` instead of `"couchbase://my.dev.server.net/"` – dnault Jul 21 '22 at 20:19
  • 2
    One last comment: Couchbase 5.1 reached end of life back in October 2021. I'm not sure if that's the cause of this issue, but at some point you may want to upgrade to a more recent version. – dnault Jul 21 '22 at 20:21
  • 3
    After Connect you might have to do cluster.Bucket("mybucket"); Checkout https://couchbase.live/ – vsr Jul 21 '22 at 21:24
  • 1
    Thank you all for the responses... regarding the version, i dont have control unfortunately, i guess its been on the docket for a while. Regarding the system resources and connection, that may be a culprit as i am finding out and this is a dev env. Regarding the field name, there is a field named id that is the same as the document, and a field named '_id', also the same, making my first foray into this confusing. I will try the suggestion though, that looks promising. I did try with and without trailing slash and no effect, and i did try the cluster.Bucket, but will checkout the link. – Keith E. Truesdell Jul 22 '22 at 01:54

1 Answers1

3

Credit to @vsr for the answer.
All the other responses helped, but nothing worked until after I did that suggestion, adding cluster.Bucket("mybucket") after the connection.

One thing that was missing is putting in a "Bucket" name. See below...

In addition to @vsr help and answer, I just found something on the website in the docs about this.
[https://docs.couchbase.com/go-sdk/current/howtos/n1ql-queries-with-sdk.html](Couchbase Docs) In the Golang example just after getting started, it mentions in the comments of the code that 'For server versions 6.5 or later you do not need to open a bucket here' and then the next line it opens a bucket. Good information.

    cOpts := gocb.ClusterOptions{
        Authenticator: gocb.PasswordAuthenticator{
            Username: "user",
            Password: "pw",
        },
    }

    cluster, err := gocb.Connect("couchbase://my.dev.server.net/", cOpts)
    if err != nil {
        panic(err)
    }

    bucketName := "myBucket"
    cluster.Bucket(bucketName)

    qOpts := gocb.QueryOptions{}

    // create query
    queryStr := "SELECT * FROM myBucket WHERE id = '123456789'"

    rows, err := cluster.Query(queryStr, &qOpts)
    if err != nil {
        panic(err)
    }

    fmt.Printf("rows: %v\n", rows)

    for rows.Next() {
        var intfc interface{}
        err = rows.Row(&intfc)
        if err != nil {
            panic(err)
        }
        fmt.Printf("interface result: %v\n", intfc)
    }

Just adding that cluster.Bucket("myBucket") line made this work.
The server is old, and is a dev server that has a lack of resources, so I also upped the timeouts knowing that it was going to be slow. I upped the timeouts by adjusted the cluster options (cOpts named in the code) to the following...

    cOpts := gocb.ClusterOptions{
        Authenticator: gocb.PasswordAuthenticator{
            Username: "user",
            Password: "pw",
        },
        TimeoutsConfig: gocb.TimeoutsConfig{
            ConnectTimeout: 95 * time.Second,
            QueryTimeout:   95 * time.Second,
            SearchTimeout:  95 * time.Second,
        },
    }

This would up the timeout to 95 seconds, and I didn't need that much, but the server was slow enough that it was taking 40 seconds in the UI for the same query, so I just wanted to make sure.
I also adjusted the timeout for the query. I am not sure what the difference is between them, but I adjusted this below.

    qOpts := gocb.QueryOptions{}
    qOpts.Readonly = true
    qOpts.ScanWait = 95 * time.Second
    qOpts.Timeout = 95 * time.Second

Additionally, I am new to couchbase if you couldn't tell, the query was not using an index field. I looked up the indexed fields for that bucket and added it to the query and that more than halved the time.

EDIT: Using the USE KEYS statement in N1QL seems to be really fast, faster than any query. I adjusted the code so the qryStr query string was like below...

queryStr := "SELECT * FROM myBucket USE KEYS ['123456789']"
Keith E. Truesdell
  • 552
  • 11
  • 21
  • 2
    CREATE INDEX ix1 ON myBucket(id); see if improves. Checkout https://index-advisor.couchbase.com/indexadvisor/#1 – vsr Jul 22 '22 at 15:43
  • 1
    Awesome resources, something good to know. I also just tried the `USE KEYS ['data',...]` statement in the N1QL and that was blazing fast. – Keith E. Truesdell Jul 22 '22 at 16:16
  • 3
    If you already know document keys , you can use USE KEYS or key value get https://couchbase.live/examples/basic-go-kv-get – vsr Jul 22 '22 at 17:47