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!
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).