CouchDB update handlers: document id must not be e

2019-09-05 06:59发布

问题:

I wrote simple update handler:

 {
   "handler": "function (doc, req) { if (req.userCtx.roles.indexOf('editor') < 0) return [req.userCtx, 'access error']; if (!doc) { return [doc, 'nothing']; } doc.date = new Date(); doc.edited_by = req.userCtx.name; return [doc, toJSON(doc)]; }"
}

When I'm trying to query from Mozilla HttpRequester http://192.168.0.34:5984/records/_design/records/_update/handler, i'm getting

with that's data

{"title":"testtest","content":"test"}

And getting

{"error":"bad_request","reason":"Document id must not be empty"}

I've added _id to JSON

{"_id":"testid","title":"testtest","content":"test"}

No luck.


Update: and running that query in browser returns nothing, which may indicate that there's no document sent, but that's not true. What i'm doing wrong?

回答1:

In CouchDB update handler _id never been set automatically, so you must do it manually. The simplest solution is using uuids, which available at req.uuid.


One important thing about update handlers. Their syntax someplace strange: you can't take data and return doc, no. Your update handler taking doc and req objects, where first is a changing document (check document existence using !doc, if it returns true — you can create new) and the second is request data, including access info, uuid and body. We're getting data from server not in req, but in req.body, which is raw string. Is must be parsed first using JSON.parse(req.body). After doing some checks, we can return — but return also not easy. If we have a doc — we're changing it, if not — we're creating new object. Return must be done by array [data_to_be_written, return_data], where first item is document for database and the second is a string (and only string, use toJSON(object) to return objects).


In addition there's my update handler function example, there's a lot of dirty debug code and it can be wrong, but it working on creation (update still unchecked).

function (doc, req) {
    if (req['userCtx']['roles'].indexOf('editor') < 0) {
        return [null, 'Access denied'];
    }
    var rcv = JSON.parse(req.body);
    if (!doc) {
        if (!rcv['_id'] && !!rcv['title'] && !!rcv['content']) {
            return [{ '_id':req.uuid,'title': rcv['title'], 'content': rcv['content'], 'date': new Date(), 'edited_by': req['userCtx']['name'] }, 'Created' + toJSON(req)];
        }
        return [null, 'Empty' + toJSON({ 'no_id': !rcv['_id'], 'title': !!rcv['title'], 'content': !!rcv['content'], 'body':req.body })];
    }
    doc['date'] = new Date();
    doc['edited_by'] = req['userCtx']['name'];
    return [doc, 'Edited' + toJSON(doc)];
}

P.S> and remember, that even update handler working over validation func, so if your data can't pass validation, it will not be written anyway.