I wanted to have a View that emits values based on keys that come from multiple documents and I managed to do it by getting linked documents inside the emit function but then my index is updated only when the base document is updated and not when one of the linked documents is being updated.
So my base documents are structured like these (minimal version):
Your idea is not possible given the way that views work. There is a requirement that the map function is “pure” (i.e. does not rely on any external state, and that any given set of input properties will always produce the same result). Anything you’d like to emit needs to be directly included in the document that is being indexed so the properties in question need to be a part of the visit document itself and not in a separate one.
Ok it make senses. But do you have any idea on how to implement the desire behavior? Those documents cannot be merged into a single one as it will break down an already existing architecture.
I could split the query into 2 views (one using the result of the other) but it doesn’t seems to be really efficient.
The usual way to do this is to have both types of documents emit the same key (in this case the visitID), and the desired properties as the value. Then you can either query for all rows with the desired visitID and merge the values together, or you can use a reduce function that does the same thing.
(Also, it seems weird in your code that you’re putting all those values into the key. Did you intend to create a multi-level sort on (id, status, isComplete, patientID) or was that a mistake?)
I got the talk you’re talking about: https://youtu.be/mFQTGiCEHrE?t=1090
I’m gonna try it and see if I manage to make it working with my documents structure.
Maybe I don’t fully understand the reduce function but it doesn’t seem to be what I’m searching for.
I want to be able to query something like this:
Return all patientId where there is a visit with status X and at least one of the event linked to the visit has isComplete to false and the configurableMetadataId = Y
So my keys are isComplete and configurableMetadataId that comes from event doc types plusstatus that comes from the visit document.
I tried to use pseudo-joins as stated inside the video but I’m struggling on how to use it with my use case as I don’t need to aggregate values but add a property in the returned value.
I updated my emit function:
String docType = (String) properties.get(FIELDS.TYPE);
String patientFullName = getPatientFullName(properties);
String key = ((String) properties.get(FIELDS.PATIENT_ID));
List<Object> values = new ArrayList<>(Arrays.asList(docType, patientFullName));
switch (docType) {
case Config.CB_EVENT_DOC_TYPE:
values.addAll(Arrays.asList(properties.get(FIELDS.CONFIGURABLE_METADATA_ID), properties.get(FIELDS.IS_COMPLETE)));
break;
case Config.CB_VISIT_DOC_TYPE:
values.add(Collections.singletonList(properties.get(CouchbaseVisitManager.FIELDS.STATUS)));
break;
}
if (key != null)
emitter.emit(key, values);
And I added a reduce function but I don’t really know how to implement it:
Have you considered just storing the events as an array in the visit document? That would make your querying much easier. This isn’t a SQL database, you don’t have to normalize…
Unfortunately we have some reasons to not change our data structure (it is already used in prod, it’s focused on offline first and try to avoid conflicts by keeping the atomicity of the data, etc.). I managed to fix it by combining 2 queries. I may update my answer once we get into couchbase lite 2.x (it seems the N1QL-like feature gives more flexibility on the way to get data out from local databases).