4

I am having couchbase documents stored in below format:

{
"userEmail": "satyam@xyz.com",
"hashedPassword": "$2a$12$MT31FHNEbOAKpQGzLdBB3uhLlPlGNU0cvsgi/2pt4TdwPjvrUzkSG",
"type": "user",
}

I want to read only the document which is having userEmail value as satyam@xyz.com. For this I wrote a couchbase view:

function (doc, meta) {
  if(doc.userEmail == "satyam@xyz.com")
      emit(doc.data, meta.id);
}

Now what I want is, I want to pass value "satyam@xyz.com" from the Java code. I tried it a lot but couldn't find a proper solution. Can anybody help me out from this dilemma.

Thanks in advance for any kind of suggestions.

Yo Yo Saty Singh
  • 539
  • 1
  • 6
  • 15

2 Answers2

7

I think in fact you want to map your JSON documents by userEmail, so your map function should be something like this:

function(doc, meta) {
    //maybe check the type of the document here, see meta.type
    emit(doc.userEmail, null)
}

Two notes:

  • if you have both json and non-json documents in your bucket you can map only json documents by checking meta.type == "json".
  • the resulting index will always have the document's ID, there's no need to emit it (or the whole document) as it grows the index size unnecessarily.

Now you can query the view by passing startkey and endkey arguments, with a little trick:

?startkey="theEmail"&endkey="theEmail\uefff"

Here \uefff is the first unicode char, which allows to simulate an exact key match since there no other combination of characters between "myEmail" and "myEmail\uefff".

Simon Baslé
  • 27,105
  • 5
  • 69
  • 70
  • If i want to get the documents greater than some value (that value to be dynamic from Java), , how to i do it? – Sivailango Jul 14 '15 at 08:47
  • 1
    @Sivailango just use `startkey` (but it will be greater or equal, in alphabetical order) – Simon Baslé Jul 15 '15 at 07:28
  • I made a mistake, the special char to use is `\uefff`(fixed in answer) – Simon Baslé Jul 15 '15 at 07:31
  • @SimonBaslé Yes you are right. Another doubt is, then we should use that key in emit function. Right? If i want to get the documents with country=us, age>28, how do i write emit? `emit([doc.country, doc.age], null)`. Now if set the value for `startkey=28`, will it automatically apply to age field? or should we set both dynamic values in startkey – Sivailango Jul 15 '15 at 07:53
  • 1
    @Sivailango you should set both values in `startkey` but then I think it will do a >= on the country as well... in this case, maybe use `["us", 28]` as the startkey and `["us", 999]` as the endkey for example... – Simon Baslé Jul 15 '15 at 07:58
3

Here is a question for you. If you have the email address and the email address is unique or you can have something like a userID being unique, why not make that the object's key? Then you do not have to have a view at all. Your app knows what it needs and gets the object by key. This is always much faster and preferable over using a view. Just something to consider.

In Couchbase you have 256 bytes (iirc) for the key, so make the key something meaningful to your application and do away with that view perhaps?

NoSQLKnowHow
  • 4,449
  • 23
  • 35
  • this would indeed actually be better – Simon Baslé Dec 15 '14 at 17:10
  • The suggestion is good guys, but I have another logic for couchbase document keys to make is unique & secure. @simon- I am sorry to say, I do not have enough reputation to mark your answer as accepted. :( – Yo Yo Saty Singh Dec 15 '14 at 17:24
  • Then it might be worthwhile to break out the email address into a separate key if this is something you are going to access often. Just something to think about. The more you can access objects by the key and not by views, the better performance you will have. – NoSQLKnowHow Dec 15 '14 at 23:19
  • @kirk - According to my project needs, I am encrypting UUID and a secret key together to generate the CB document. – Yo Yo Saty Singh Dec 16 '14 at 05:32