I have the following view
{
"views" : {
"categories" : {
"map" : "function (doc) { emit(doc._id,{"title":doc.title,"parentnode":doc.parentnode});}"
}
}
}
i.e., for each document, return a JSON object with two keys : title
and parentnode
with their respective values. The view runs just fine in the cloudant UI
{
"id": "3bacce314363eb954f1922ff3cd2240c",
"key": "3bacce314363eb954f1922ff3cd2240c",
"value": {
"title": "poi",
"parentnode": "asd"
},
"_id": "3bacce314363eb954f1922ff3cd2240c"
}
which is perfect. Now i try to read this in my Java program as
List<JSONObject> vals = cloudant.getViewRequestBuilder("categoryDesign", "categories")
.newRequest(com.cloudant.client.api.views.Key.Type.STRING, JSONObject.class)
.includeDocs(true)
.build()
.getResponse()
.getValues();
Note that JSONObject
in this case is org.json.JSONObject;
. But for this i get
[{}]
so then i changed the view a little bit
{
"views" : {
"categories" : {
"map" : "function (doc) { emit(doc._id,doc.title+":"+doc.parentnode);}"
}
}
}
and in the cloudant UI i see
{
"id": "9db1f03e8f4d239a6e18d4612b1a4275",
"key": "9db1f03e8f4d239a6e18d4612b1a4275",
"value": "poi:asd",
"_id": "9db1f03e8f4d239a6e18d4612b1a4275"
}
and now i do
List<String> vals = cloudant.getViewRequestBuilder("categoryDesign", "categories")
.newRequest(com.cloudant.client.api.views.Key.Type.STRING, String.class)
.includeDocs(true)
.build()
.getResponse()
.getValues();
Now, the output is
["poi:asd"]
What can i do to read the values as JSONObject
s ?
Follow Up: How can i remove the duplicates from the output of the view?
Cloudant client does not seem to work with org.json.JSONObject
. I got your first example to work with com.google.gson.JsonObject
and org.apache.wink.json4j.JSONObject
. Here are the maven dependencies:
com.google.gson.JsonObject:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.7</version>
</dependency>
org.apache.wink.json4j.JSONObject:
<dependency>
<groupId>org.apache.wink</groupId>
<artifactId>wink-json4j</artifactId>
<version>1.4</version>
</dependency>
Output from System.out.println(vals.toString())
:
[{"parentnode":"asd","title":"poi"}]
To answer the followup question:
You can eliminate duplicates by using a reduce function (sum or count) in your view, but this also would require that you change your key to be the unique key for the data. So, if the combination of title and parentnode is what you want to be your unique key, your view would look like this:
"categoriesNoDups": {
"reduce": "_sum",
"map": "function (doc) { emit([doc.title, doc.parentnode], 1); } }"
}
Now, when you call your view (note the new view is named categoriesNoDups
) you want to add ?group=true
like so:
https://youraccount.cloudant.com/yourdb
/_design/categoryDesign/
_view/categoriesNoDups?group=true
The data will look similar to the following:
{
"rows": [
{
"key": [
"poi",
"asd"
],
"value": 2
}
]
}
Now, instead of getting the values you want to get the keys. To retrieve the keys in Java you would do something like this:
List<Key.ComplexKey> keys = cloudant.getViewRequestBuilder("categoryDesign", "categoriesNoDups")
.newRequest(Key.Type.COMPLEX, Number.class)
.group(true)
.build()
.getResponse()
.getKeys();
for (Key.ComplexKey key : keys) {
JSONArray keyValues = new JSONArray(key.toJson());
System.out.println("title = " + keyValues.getString(0));
System.out.println("parentnode = " + keyValues.getString(1));
}
Now you're back to dealing with arrays instead of JSON objects. Also note: I am using the Apache Wink JSON library to convert the keys to JSON objects (which are just arrays) and then accessing the values from those objects. The output looks similar to the following:
title = poi
parentnode = asd