How to get array of data from Document properly (CBL) on Android

594 views
Skip to first unread message

Mart-Indrek Süld

unread,
Apr 8, 2014, 9:59:31 AM4/8/14
to mobile-c...@googlegroups.com
I'm developing Couchbase Lite on Android and I have a database, what is initialized according to JSON data file, what looks like this:
{
    "categories": [
        {
            "name": "Financial",
            "books": [
                {
                    "name": "Rich dad poor dad"
                },
                {
                    "name": "How to stay rich"
                }
            ]
        },
        {
            "name": "Science",
            "books": [
                {
                    "name": "Superman"
                },
                {
                    "name": "Green hornet"
                }
            ]
        }
    ]
}

How can I receive the "books"-array and gain access to "name"-value for certain category?

I separated all the categories in a database to a separate Documents and gave them ID according to category name(Is it reasonable to separate them or it doesn't make any difference?).
For example, if i want to get access to "financial" category i type:
Document d = database.getExistingDocument("financial");
and everything works fine. 

If i want to get all the categories i type:
List<Category> list = new ArrayList<Category>();
Database db = manager.getExistingDatabase(DATABASE_NAME);
Query query = db.createAllDocumentsQuery();
QueryEnumerator rowEnum = query.run();
for (Iterator<QueryRow> it = rowEnum; it.hasNext();) {
   QueryRow row = it.next();
   Document d = db.getExistingDocument(row.getDocumentId());
   list.add(new Category((String) d.getProperty("name")));
}

But how can i get access to "books"-array?
So far this is what i've come up with (Read APIs and GrocerySync example):
Document d = db.getExistingDocument(categoryID);
com.couchbase.lite.View viewItemsByDate = db.getView("booksForCategory");
viewItemsByDate.setMap(new Mapper() {
@Override
public void map(Map<String, Object> document, Emitter emitter) {
Object createdAt = document.get("books");
if (createdAt != null) {
emitter.emit(createdAt.toString(), document);
}
}
}, "1.0");
com.couchbase.lite.View v = db.getView("booksForCategory");
Query q = v.createQuery();
QueryEnumerator rowEnum = q.run();
for (Iterator<QueryRow> it = rowEnum; it.hasNext();) {
QueryRow row = it.next();
Book b = new Book(row.getProperty("name"));//???
}
But in my oppinion, it doesen't work correctly and this is not the way to do it. It returns wrong results and i'm pretty sure this is not how it should be done. 

(Oh, Do i define "getView("booksForCategory")" once in the constructor of the DAO or every single time?)

Could anyone help me and show me how it's done properly? How to properly get the array of data from the Document so i can get access to properties using Key's?

Thanks in advance!

prasanna kumar

unread,
Apr 9, 2014, 9:21:41 AM4/9/14
to mobile-c...@googlegroups.com
Hi,
It may help you

com.couchbase.lite.View viewItemsByDate = db.getView("booksForCategory");
viewItemsByDate.setMap(new Mapper() {

HashMap<String, Object> categories = (HashMap<String, Object>) document
.get("categories");

@Override
public void map(Map<String, Object> document, Emitter emitter) {

HashMap<String, String> books= (HashMap<String, String>) categories
.get("books");

Object createdAt = books.get("name");
if (createdAt != null) {
emitter.emit(createdAt.toString(), document);
}
}
}, "1.0");

//In Query part
Query q = v.createQuery();
QueryEnumerator rowEnum = q.run();
for (Iterator<QueryRow> it = rowEnum; it.hasNext();) {
QueryRow row = it.next();
     //BY USING Getkey method we can get name field
Book b = new Book(row.getKey()));
     //or else we can do like this also
HashMap<String, HashMap<String, String>> responsibleHaspMap = (HashMap<String, HashMap<String, String>>) document
.getCurrentRevision().getProperty(
"categories");
responsibleHaspMap
.get("books").get("name"));
}

Mart-Indrek Süld

unread,
Apr 11, 2014, 9:17:06 AM4/11/14
to mobile-c...@googlegroups.com
Thank you, but it doesn't seem to work. I get NullPointerExceptions from the Map. It seems to me this particular predefined map gives access to only "Name"key property, but i need access to whole object. 

In short - i'd really like to know how to get access to second level array objects properties.

If you'd be able to help me out, i'd be so grateful! 

Mart-Indrek Süld

unread,
Apr 14, 2014, 4:22:05 AM4/14/14
to mobile-c...@googlegroups.com
After numerous articles, APIs and youtube videos, i got it to work. 

Here's my code with few comments:

View gamesForCategory = db.getView("viewName");
gamesForCategory.setMap(new Mapper() {
@Override
public void map(Map<String, Object> document, Emitter emitter) {
showText("Doing query for: " + categoryID );
if(document.get("name").equals(categoryID)){
Object gamesData = document.get("books"); //get second level array object
List<Object> gamesList = (List<Object>) gamesData; //since it's a list, i can cast it
for(Object g : gamesList){
Map<String, Object> m = (Map<String, Object>) g;
emitter.emit(m.get("name"), m); //'m.get("name")' is ID for the query result. 'm' is an object in second level array and will be pushed into the results
}
}
}
}, "1.0");

View v = db.getView("descriptionsForCategory");
Query q = v.createQuery();
QueryEnumerator rowEnum = q.run();
for (Iterator<QueryRow> it = rowEnum; it.hasNext();) {
QueryRow row = it.next();
Map<String, Object> m = (Map<String, Object>) row.getValue(); //only second level array objects are in results, so i can cast them to map
showText(m.get("name").toString()); //get any value from map using keys.
}
Reply all
Reply to author
Forward
0 new messages