Couchbase Lite View with multiple reduce functions

I have a View with a Map function and I want to be sure it doesn’t return duplicates. For this I based my solution on the solution provided by this StackOverflow post. This add a reduce function to the original map.

But I also want to get the size of the final result. For this I 've written a simple reduce function:

if (rereduce)
    return com.couchbase.lite.View.totalValues(values);
else
    return values.size();

But how do I combine both reduce functions? I want to be able to query the view with only the first reduce function (filtering) or with both (filtering + counting). I’m pretty sure the rereduce parameter may help on this but I’m not sure to fully understand its behavior.

Thank’s.

(I’m using CBL Android 1.x)

That’s not what the rereduce parameter is for. That was meant for future expansion but never actually got implemented before we moved away from map/reduce for version 2.0. You will have to use reduce to filter out the duplicates and then count them using standard techniques.

But what if I’m using the limit attribute? I want to have the total size of the result, not the limited size. I understand that the version 2.0 will enable that behavior through the N1QL-like feature but we’re not ready to upgrade it right now.

Do you think about any workaround? I think that I could get the total size by running the query without any limit attribute but this would be a little overkill.

Thanks.

Even the count reduce function would result in the whole query being run. It’s not as intensive as a query from other technologies because the intensive part is the indexing. The query basically just iterates through the rows in the existing index.

To use a second reduce function, you’ll need to make a second view with the same map function. Which would be somewhat wasteful.

Yes and they can’t chain each other. I’ve a another question : does the post filter is executed after or before the “limit” on a query? It may help me to accomplish the desired behavior.

Thanks.

IIRC, the post-filter runs before the limit is applied, otherwise you wouldn’t get as many docs as you asked for.

I finally used the reducer for counting and a postFiler like the one below for removing duplicates:

public class DuplicateValueIdPostFilter implements Predicate<QueryRow> {
    public static final String TAG = DuplicateValueIdPostFilter.class.getSimpleName();
    private final Set<String> ids = new HashSet<>();

    public DuplicateValueIdPostFilter() {
        ids.clear();
    }

    @Override
    public boolean apply(QueryRow row) {
        final String id = (String) row.getValue();
        if(ids.contains(id))
            return false;
        ids.add(id);
        return true;
    }

    public void reset() {
        ids.clear();
    }
}