2

I have been struggling with a problem related to querying Couchbase lite 1.4 database on my mobile Android device. It seems for me that I don't fully understand how querying using MapReduce Views works like.

So I have the following setup:

1) Database that contains entities like so:

{
  dateCreated: 1220227200,
  relatedObjectId: "objectId_23445"
  type: "mytype"
}

2) I would like to query my database and get all objects of type "mytype", which are related to object with a given id (relatedObjectId field) and sorted by dateCreated field.

Here is my map function which generates a view:

public void map(Map<String, Object> document, Emitter emitter) {
    if (document.get("type") != null && document.get("type").equals("mytype")) {
        List<Object> keys = new ArrayList<Object>();
        keys.add(document.get("dateCreated");
        keys.add(document.get("relatedObjectId"));
        emitter.emit(keys, null);
    }
}

3) This function produces results like so:

[1220227200, objectId_23445],
[1220227201, objectId_3],
[1220227202, objectId_7],
[1220227203, objectId_8],
[1220227204, objectId_23445]

4) I want to get all objects with an id "objectId_23445" sorted by date like so:

[1220227200, objectId_23445],   
[1220227204, objectId_23445]

5) But as a result I always get all objects from a database.

First dateCreated seems to be taken into account but my second part of a key (relatedObjectId) does not really takes part in filtering. So I always get a list from point 3.

My query looks like so:

String relatedObjectId = "objectId_23445"
Query query = CouchbaseViews.GetAllMyTypeItems().createQuery();            
query.setDescending(true);

ArrayList<Object> startKey = new ArrayList<Object>();
startKey.add(0);
startKey.add(relatedObjectId);

ArrayList<Object> endKey = new ArrayList<Object>();
endKey.add(Calendar.getInstance().getTimeInMillis());
endKey.add(relatedObjectId);

query.setStartKey(endKey);
query.setEndKey(startKey);

So I need help with this. In my opinion I just don't understand how to filter objects when key is a compound key (arrayList in my case).

Ofc as a workaround I can only emit relatedObjectId and then sort data manually but is this a correct way to do so?

Any help will be appreciated, thanks in advance!

alexrnov
  • 2,346
  • 3
  • 18
  • 34

1 Answers1

2

I solved my problem after some additional research (including some posts on stackoverflow).

It seems like in order to achieve what i wanted first of all i have to reverse an order in map() function:

public void map(Map<String, Object> document, Emitter emitter) {
    if (document.get("type") != null && document.get("type").equals("mytype")) {
        List<Object> keys = new ArrayList<Object>();    
        //order of elements have been changed                        
        keys.add(document.get("relatedObjectId"));
        keys.add(document.get("dateCreated");
        emitter.emit(keys, null);
    }
}

After this modification our map() function produces followig output:

[objectId_23445, 1220227200],
[objectId_3, 1220227201],
[objectId_7, 1220227202],
[objectId_8, 1220227203],
[objectId_23445, 1220227204]

And finally i have to modify my query like so:

String relatedObjectId = "objectId_23445"
Query query = CouchbaseViews.GetAllMyTypeItems().createQuery();            
query.setDescending(true);

ArrayList<Object> startKey = new ArrayList<Object>();            
startKey.add(relatedObjectId);

ArrayList<Object> endKey = new ArrayList<Object>();
endKey.add(relatedObjectId);
endKey.add(new HashMap<>());

query.setStartKey(endKey);
query.setEndKey(startKey);

Now my query will select all elements with a relatedObjectId first and then sort this sequence and since we will always have the same prefix for all elements (relatedObjectId), second item will be taken into account during sorting (dateCreated).

alexrnov
  • 2,346
  • 3
  • 18
  • 34