Couchbase Lite View with multiple reduce functions


#1

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)


#3

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.


#4

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.


#5

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.


#6

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


#7

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.


#8

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


#9

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();
    }
}