Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

start_time and end_time confusion #4

Open
airomega opened this issue Nov 3, 2016 · 3 comments
Open

start_time and end_time confusion #4

airomega opened this issue Nov 3, 2016 · 3 comments

Comments

@airomega
Copy link

airomega commented Nov 3, 2016

I tried using the couchgo View option and either misunderstood it or hit a bug.

I want to use start_time and end_time as outlined on the couchdb api:
https://wiki.apache.org/couchdb/HTTP_view_API#Querying_Options

The start and end_times should have format [time]

I create url.Values
params := url.Values{lumencouch.IncludeDocs:[]string{"true"}, lumencouch.StartKey:[]string{startKey)}, lumencouch.EndKey:[]string{endKey)}}

However when I query the params end up being:

end_key=1478192152775412649&include_docs=true&start_key=1478192092063988716

It seems that as this was a single value in an array the square braces are removed and the query doesn't work

I tried adding the braces manually
params := url.Values{lumencouch.IncludeDocs:[]string{"true"}, lumencouch.StartKey:[]string{fmt.Sprintf("[%s]",startKey)}, lumencouch.EndKey:[]string{fmt.Sprintf("[%s]",endKey)}}

However, this resulted in the braces being encoded

end_key=%5B1478193145176006200%5D&include_docs=true&start_key=%5B1478193025035134981%5D 200

I'm guessing the keys parameter might be of some assistance here but it's not clear how.

Is this a bug or an I misunderstanding something?

@airomega
Copy link
Author

airomega commented Nov 4, 2016

I don't think this an issue in with couchgo - I think this is an issue with couchdb having a bad api.

Golangs net.url requires the Values to be in format map[string][]string

In the couchgo Client UrlString correctly calls the following:

u.RawQuery = values.Encode()

So it's impossible to pass a string array as a value and if you try to pass "[val]" it encodes the square brackets. I don't think Go is wrong here - I think the couchdb API is not well formed.

Any suggestions of a workaround would be welcome but I guess I can just Get the URL directly without using the client.View function.

@lancecarlson
Copy link
Owner

This is an interesting issue! To be honest, I haven't looked at this library in a long time. Any suggestions how it could be made to work without blowing up existing functionality?

@airomega
Copy link
Author

airomega commented Nov 7, 2016

I've found a workaround however it's not pretty and there may be a better method. It also seems I have to bypass couchgo.View. As mentioned previously I don't think this is the fault of couchgo - it seems to be shortsightedness of the couch view API not conforming to JSON standards

The following is a struct I've created which allows me to accomplish my goal - frankly I hate the implementation. I check for the members which require [ ] - extract the values from the params map, delete the values from the params map, encode the params map and then concatenate the values onto the encoded string.

Feel free to suggest a better method :)


type CouchView struct {
    CouchDB    *CouchDatabase
    Design     string
    View       string
    Params     *url.Values
    Keys       *[]string
}

const viewString = `/_design/%s/_view/%s?%s`

func (cv *CouchView) GetResult() (*couch.MultiDocResponse, error) {
    baseUrl := cv.CouchDB.getURL()
    fullURI := baseUrl + cv.getQueryString()
    return queryView(fullURI)
}

func (cv *CouchView) getQueryString() string {
    sKey := cv.Params.Get(StartKey)
    cv.Params.Del(StartKey)
    eKey := cv.Params.Get(EndKey)
    cv.Params.Del(EndKey)

    queryString := cv.Params.Encode()

    if len(sKey) > 0 {
        queryString = queryString + fmt.Sprintf("&%s=[%s]", StartKey, sKey)
    }

    if len(eKey) > 0 {
        queryString = queryString + fmt.Sprintf("&%s=[%s]", EndKey, eKey)
    }

    return fmt.Sprintf(viewString, cv.Design, cv.View, queryString)
}

func queryView(uri string) (res *couch.MultiDocResponse, err error) {
    client, err := couch.NewClientURL(uri)
    if err != nil {
        return nil, err
    }

    body := new(bytes.Buffer)
    req, err := client.NewRequest("GET", uri, body, nil)
    if err != nil {
        return nil, err
    }

    httpResp, err := http.DefaultClient.Do(req)
    if httpResp.StatusCode != 200 {
        return res, errors.New(httpResp.Status)
    }
    if err != nil {
        return nil, err
    }

    respBody, err := ioutil.ReadAll(httpResp.Body)
    if err != nil {
        return nil, err
    }

    if err = json.Unmarshal(respBody, &res); err != nil {
        return nil, err
    }
    return res, nil
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants