0

I need get doc where createdBy=userId or updatedBy= userId. I have next map func in CouchDB:

function (doc) {
                        if (doc.$doctype === 'Records') {
                            emit([doc.createdBy, doc.updatedBy], doc);
                        }
                    }

And node.js backend

getData: async (userId) => {
        return await adapter.getRows(
            'Records', 'url',
            {
                startkey: [userId, userId],
                endkey: [userId],
            }
        );
    }

but it works as operator AND. Please help me find mistake.

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Volodymyr Zh
  • 317
  • 7
  • 19
  • Why use array key? emit(doc.createdBy, null); emit(doc.updatedBy, null) in view will allow you to request with keys:[userId1, userId2, ...] to get union (however probably with dupes). – ermouth Jun 03 '18 at 02:36
  • 1
    Since CouchDB 2.x, you can use OR with a [mango query](http://docs.couchdb.org/en/2.1.1/api/database/find.html). See the [combination operators](http://docs.couchdb.org/en/2.1.1/api/database/find.html#combination-operators). – Jonathan Hall Jun 06 '18 at 07:26
  • @Flimzy please tell me, how I can combine mango query and view or I need change request in node ? I create mango query in Fauxton - it is works, but I don't understand how use it with view and node.js ... – Volodymyr Zh Jun 07 '18 at 12:05
  • You don't combine them. You'd need to change to a mango query. – Jonathan Hall Jun 07 '18 at 12:51

2 Answers2

0

From my understanding, you can't do a OR from a single request yet.

(As of CouchDB 2.1, the _queries endpoint is not yet available. In the future, you will be able to request multiple queries in the same HTTP request).

Using startkey and endkey syntax, OR would be the equivalent of:

createdBy

  • startKey=[john]
  • endkey=[john,{}]

updatedBy

  • startKey=[null,john]

  • endkey=[{},john]

Then, you could do an union of the two result sets.

If you're using CouchDB 2.X, you should use Mango selector with the $or operator.

Other solution

You could create a specific view for this request.

For example, you would index both the updatedBy and createdBy.

if (doc.$doctype === 'Records') {
   emit([doc.createdBy, doc.createdAt]);
   emit([doc.updatedBy, doc.createdAt]);
}

Then, you can query it with startkey=[author]&endkey=[author,{}]

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Alexis Côté
  • 3,670
  • 2
  • 14
  • 30
  • I use CouchDB 1.6.1 and I try next func: `emit([doc.updatedBy, doc.createdAt] || [doc.createdBy, doc.createdAt], doc);` and it works... How about it ? – Volodymyr Zh Jun 01 '18 at 13:55
  • Hum, I don't see how it works. [a,b] || [c,d] gives [a,b]. So basically, it only index [doc.updatedBy, doc.createdAt] – Alexis Côté Jun 01 '18 at 14:17
  • You just made me realized another solution(I updated my answer). Also, don't ever index the doc. It put extra data in the index that is already available with the ?include_docs=true parameter – Alexis Côté Jun 01 '18 at 14:20
  • Sorry for delay and thanks for answer but I decide moved from couchDB from 1.6 to 2.1. Also if I will be use `emit([doc.createdBy, doc.createdAt]); emit([doc.updatedBy, doc.createdAt]);` I get duplicate records. – Volodymyr Zh Jun 06 '18 at 18:09
0

I would do it this way:

function (doc) {
   if (doc.$doctype === 'Records') {
       emit(doc.createdBy, "created");
       emit(doc.updatedBy, "updated");
   }
}

then you can query using a single key of the userID, the value is extra info on the action if that is needed, otherwise you can just leave it nil.

Do not emit a value of doc because that is redundant, you can always get the doc using

include_docs

query options.

Chinh Nguyen
  • 583
  • 1
  • 7
  • 14