Sorting map/reduce by values in Couchbase Lite

Hello !

Advertissement: I’m using CouchbaseLite Android 1.4.0 and I’m not ready to switch to 2.0.

To get the context of my issue:

  • I have 2 doc types: PATIENT & VISIT
  • A patient is linked to a visit by a field visitId
  • A visit has a startDateTime and a endDateTime
  • A visit is considered as ‘open’ if the endDateTime is null or missing
  • A visit can be of different types through the field visitType
  • A visit can be inactive through the field inactive

I want to:

  • Get all patients (id + name) of all open and active visits of a certain type
  • The result is paginated using skip and limit
  • Get the result sorted by name

I managed to get all the correct patients and to paginate the result but the issue is with the sorting.
I can’t make a ‘post sorting’ (getting the result in a random order and then use self-made method to sort them) because of the pagination.

So here is how it works actually without the sorting:

THE MAP/REDUCE

if (isVisit()) {
	Object inactive = document.get(FIELDS.INACTIVE);
	if(inactive == null)
		inactive = false;
		
	Document patientDoc = database.getExistingDocument(FIELDS.PATIENT_ID);

	if(patientDoc != null && patientDoc.getProperties() != null) {
		Object[] keys = {
				document.get(CouchbaseVisitManager.FIELDS.STOP_DATE_TIME),
				inactive,
				document.get(CouchbaseVisitManager.FIELDS.VISIT_TYPE)
		};
		Object[] values = {
			document.get(FIELDS.PATIENT_ID),
			patientDoc.get(FIELDS.FAMILY_NAME),
			patientDoc.get(FIELDS.FIRST_NAME)
		}
		emitter.emit(keys, values);
	}
}

THE QUERY

Query query = getQuery(Views.PATIENTS_CURRENTLY_IN_VISIT); //Helper method to create a query
query.setKeys(new ArrayList<Object>(){{
	add(new ArrayList<Object>(){{
		add(null);
		add(false);
		add(visitType);
	}});
}});
query.setSkip(skip);
query.setLimit(limit);

And this is working well to get my patients but not for sorting them.

I tried to add patient names inside the view like this:

Object[] keys = {
	patientDoc.getProperties().get(FIELDS.FAMILY_NAME),
	patientDoc.getProperties().get(FIELDS.FIRST_NAME),
	document.get(FIELDS.STOP_DATE_TIME),
	inactive,
	document.get(FIELDS.VISIT_TYPE)
};

And update my query.keys like this:

query.setStartKey(new ArrayList<Object>(){{
	add(null);
	add(null);
	add(null);
	add(false);
	add(visitType);
}});
query.setEndKey(new ArrayList<Object>(){{
	add(new HashMap<>());
	add(new HashMap<>());
	add(null);
	add(false);
	add(visitType);
}});

But this returns no patients (result.size = 0)

So… I don’t know how to achieve my goal.
I tought of a way to sort by values but it doesn’t seem to exist yet (should wait for 2.0 I think). But is their any workaround to achieve this kind of behavior?

Thank’s for reading.

Answered on Stack Overflow: https://stackoverflow.com/questions/48791551/couchbase-lite-sorting-map-reduce-by-values

You’ll have to do the pagination in memory, i.e. run the entire query and then pull out the range of rows you want.

(I know that’s not optimal, but it’s the same as what would happen behind the scenes if you did a similar query in SQLite.)