0

I have Json Documents in the following format

Name :
Class :
City :
Type :
Age :
Level :
Mother :
Father :

I have a map function like this

function(doc,meta)
{
    emit([doc.Name,doc.Age,doc.Type,doc.Level],null);
}

What I can do is give "name" and filter out all results but what I also want to do is give "age" only and filter out on that. For that couchbase does not provide functionality to skip "Name" key. So I have to create a new map function which has "Age" as first key, but I also have to query on only "Level" key also so like this. I would have to create many map functions for each field which obviously is not feasible so is there anything I can do apart from making new map function to achieve this type of functionality? I can't us n1ql because I have 150 million documents so it will take a lot of time.

James Z
  • 12,209
  • 10
  • 24
  • 44
Legendary_Hunter
  • 1,040
  • 2
  • 10
  • 29

1 Answers1

2

First of all - that is not a very good reduce function.

  1. it does not have any filtering
  2. function header should be function(doc, meta)
  3. if you have mixture between json and binary objects - add meta.type == "json"

Now for the things you can do:

  1. If you are using v4 and above (v4.1 in much more recommended) you can use N1QL and use it very similar to SQL language. (I didn't understand why you can't use n1ql)
  2. You can emit multiple items in multiple order

i.e. if I have doc in the format of

{
  "name": "Roi",
  "age": 31
}

I can emit to the index two values:

function (doc, meta) {
  if (meta.type=="json") {
    emit(doc.name, null);  
    emit(doc.age, null);
  }
}

Now I can query by 2 values. this is much better than creating 2 views.

Anyway, if you have something to filter by - it is always recommended.

Roi Katz
  • 575
  • 4
  • 14
  • my mistake I wrote incorrect header function in my post. Anyways multiple emit wont solve my problem because assume i have two emits like this emit(doc.age,null) emit(doc.level,null); Now I pass 1 value to key to filter all docs having age 1. But it will also give me those documents having level 1. So multiple emits wont help when two fields have same value – Legendary_Hunter Mar 04 '16 at 15:45
  • 1
    You can attach string before it, something like: `function (doc, meta) { if (meta.type=="json") { emit("name_" + doc.name, null); emit("age_" + doc.age, null); } }` – Roi Katz Mar 04 '16 at 15:47
  • What will be my json document format? like this ` "name" : "name_legendary" ` – Legendary_Hunter Mar 07 '16 at 06:24
  • It wouldn't effect your JSON (data). your document will remain the same. The only thing that will change is your view and they query string that you can access as a key. You will be able to refer back to the original doc normally. – Roi Katz Mar 07 '16 at 06:39
  • Okat thanx this method worked. But is there anyother more dynamic method like I have 20 columns and for this method to work I have to make emit of each and every combination and so there will be many combinations. Is there any more general method like in n1ql we have **where clause** ? – Legendary_Hunter Mar 07 '16 at 07:04
  • If you need to filter like N1QL - use N1QL. Have you tried with covering indexes? View are more suited for when you know what you want to do, do it a lot, and do more or less the same query with something like where, Like reporting, they are incremental and pre-computed. This tool is not something dynamic, it's not the purpose of that tool. If you need more ad-hoc style - N1QL is the tool - or use it how I showed. What will be faster? depending the usage. currently - might be views. in 4.5 maybe N1QL. – Roi Katz Mar 07 '16 at 07:14
  • N1QL is very slow for me because I have many documents in production. Anyways I'll try to use the method you specified above – Legendary_Hunter Mar 07 '16 at 08:03
  • Slow might be, depending the queries. but I strongly suggest that you try covering indexes with N1QL [some info](http://blog.couchbase.com/2015/november/covering-indexes-for-n1ql) – Roi Katz Mar 07 '16 at 08:10