0

I have below response from my map reduce . Now i want to count the number of rows in the response can any one help me how i can do it in cloudant? I need something in response like to get the total count of distinct correlationid in a period.

{
rows: [
{
key: [
"201705",
"aws-60826346-"
],
value: null
},
{
key: [
"201705",
"aws-60826348802-"
],
value: null
},
{
key: [
"201705",
"aws-las97628elb"
],
value: null
},
{
key: [
"201705",
"aws-ve-test"
],
value: null
},
{
key: [
"201705",
"aws-6032dcbce"
],
value: null
},
{
key: [
"201705",
"aws-60826348831d"
],
value: null
},
{
key: [
"201705",
"aws-608263488833926e"
],
value: null
},
{
key: [
"201705",
"aws-608263488a74f"
],
value: null
}
]
}
Community
  • 1
  • 1
Lucifer007
  • 107
  • 1
  • 14
  • Possible duplicate of [Select distinct count cloudant/couchdb](https://stackoverflow.com/questions/31105250/select-distinct-count-cloudant-couchdb) – Raj May 22 '17 at 18:21
  • is the key (an array) your `correlationid`, or is the 2nd element in the array `correlationid`? – Raj May 22 '17 at 18:23
  • correlationid is the 2nd element in the array – Lucifer007 May 23 '17 at 04:34

2 Answers2

1

You need to implement a slightly obscure concept called "chained map-reduce" to accomplish this. You can't do this in the Cloudant administrative GUI, so you'll have to write your design document by hand.

Have your map/reduce emit an array as the key. The 1st array element will be month and the second will be your correlationid. The value should be 1. Then specify the built-in _count as the reduce function.

Now you need to add the chaining part. Chaining basically involves automatically copying the result of a map/reduce into a new database. You can then do another map/reduce on that database. Thereby creating a chain of map/reduces...

Here's a tiny sample database using your example: https://rajsingh.cloudant.com/so44106569/_all_docs?include_docs=true&limit=200

Here's the design document containing the map/reduce, along with the dbcopy command that updates a new database (in this case called sob44106569) with the results of the view called view:

{
    "_id": "_design/ddoc",
    "_rev": "11-88ff7d977dfff81a05c50b13d854a78f",
    "options": {
      "epi": {
        "dbcopy":
          {
            "view": "sob44106569"
          }
      }
    },
    "language": "javascript",
    "views": {
      "view": {
        "reduce": "_count",
        "map": "function (doc) {\n  emit([doc.month, doc.machine], 1);\n}"
      }
    }
}

Here's the result of the map function (no reduce) showing 10 rows. Notice that there are two documents with month 201705 and machine aws-6032dcbce: https://rajsingh.cloudant.com/so44106569/_design/ddoc/_view/view?limit=200&reduce=false

If you just do the built-in _count reduce on this view at group_level=1, you'll get a value of 9 for 201705, which is wrong for your purposes because you want to count that aws-6032dcbce only once, even though it shows up in the data twice:

https://rajsingh.cloudant.com/so44106569/_design/ddoc/_view/view?limit=200&reduce=true&group=true&group_level=1

So let's take a quick look at the map/reduce at group_level=2. This is what gets copied to the new database:

https://rajsingh.cloudant.com/so44106569/_design/ddoc/_view/view?limit=200&reduce=true&group=true&group_level=2

Here you see that aws-6032dcbce only shows up once (but with value=2), so this is a useful view. The dbcopy part of our map/reduce creates the database sob44106569 based on this view. Let's look at that: https://rajsingh.cloudant.com/sob44106569/_all_docs?include_docs=true

Now we can run a very simple map/reduce on that database, emitting the month and machine again (now they are in an array so have different names), but this time the repeated values for machine have already been "reduced" away.

function (doc) {
  if (doc.key && doc.key.length == 2 )
    emit(doc.key[0], doc.key[1]);
}

And finally here's the count of distinct "machines". Now we can finally see the desired value of 8 for 201705.

https://rajsingh.cloudant.com/sob44106569/_design/views/_view/counted?limit=200&reduce=true&group=true&group_level=1

response:

{
  "rows": [
    {
      "key": "201705",
      "value": 8
    },
    {
      "key": "201706",
      "value": 1
    }
  ]
}
Raj
  • 544
  • 2
  • 10
  • Thanks for the response with wonderful example. I get the count,but the issue is if i have some entries with duplicate machine for the same month then it counts that also.but my requirement is to get the distinct count of machines for a month. – Lucifer007 May 24 '17 at 02:54
  • @MayankMike you're right my original answer didn't account for duplicate machines. I've updated the answer. – Raj May 24 '17 at 16:51
0

Emit 1 instead of null and use the built-in reducer _count.

xpqz
  • 3,617
  • 10
  • 16
  • Hi xpqz thanks for the response. The above json response i am getting from my below map reduce , but i want to count the number of rows in my response, as above we can see 5 rows in response so my requirnment is to get total rows with distinct correlationAssetId and group by period function (doc) { if(doc.type === "asset") { emit([doc.period,doc.correlationAssetId],1) } } – Lucifer007 May 23 '17 at 06:54
  • It can't be - each row says value: null. That suggests you're emitting null, not 1. Also, if you had set a reducer, you'd get a single value back unless you query with ?reduce=false. – xpqz May 23 '17 at 06:58
  • Although reading the question again, I think I misunderstood what you're trying to achieve - you want the number of uniques in the second component of the key for every first component of the key. – xpqz May 23 '17 at 07:01
  • Hi xpqz for more clarification please refer https://stackoverflow.com/questions/44083490/how-to-create-equivalent-view-in-cloudant-for-distinct-and-cout-query-in-mysql. sorry please bear with me i am new ti cloudant,, – Lucifer007 May 23 '17 at 07:10