CouchBase Lite,在查询中排除具有某些键的文档

And*_*Bas 5 android couchbase couchbase-view couchbase-lite

我有一个带有映射器的简单视图,它会发出带有一些键的文档。

    com.couchbase.lite.View view = database.getView(VIEW_NAME);
    if (view.getMap() == null) {
        Mapper map = new Mapper() {
            @Override
            public void map(Map<String, Object> document, Emitter emitter) {
                if ("user".equals(document.get("type"))) {
                    emitter.emit(document.get("name"), document); 
                }
            }
        };
        view.setMap(map, null);
    }
Run Code Online (Sandbox Code Playgroud)

有了这个视图,我就可以在上面创建查询,并使用某些参数,如 setKeys、startKey、endKey、setDescending、setDescending、setSkip 等,如 couchbase手册中所述。

如果我写

    Query query = view.createQuery();
    List<Object> keys = new ArrayList<>();
    keys.add("User Name");
    query.setKeys(keys);
Run Code Online (Sandbox Code Playgroud)

该查询将返回与“用户名”键匹配的所有文档。

但我找不到一种简单的方法来编写排除(省略)具有某些键的文档的查询(与 setKeys() 函数相反)

在ToDoLite 示例中发现了一个 hack 代码如下所示:

public static Query getQuery(Database database, final String ignoreUserId) {
    com.couchbase.lite.View view = database.getView(VIEW_NAME);
    if (view.getMap() == null) {
        Mapper map = new Mapper() {
            @Override
            public void map(Map<String, Object> document, Emitter emitter) {
                if ("user".equals(document.get("type"))) {
                    if (ignoreUserId == null ||
                            (ignoreUserId != null &&
                                    !ignoreUserId.equals(document.get("user_id")))) {
                        emitter.emit(document.get("name"), document);
                    }
                }
            }
        };
        view.setMap(map, null);
    }

    Query query = view.createQuery();
    return query;
}
Run Code Online (Sandbox Code Playgroud)

请注意,该视图只会排除您在第一次调用期间传递给它的键ignoreUserId ,并且在下次调用期间将忽略所有其他键(因为它只会在第一次调用期间创建一次视图)

因此,您需要为他们想要省略的每个键创建新视图。但如果你有很多想要排除的键或者经常这样做,那么它会效率低下并且是样板的。

您知道更好的解决方案或黑客吗?

如有任何帮助,
请提前致谢

hru*_*ing 5

CouchBase 不适用于您要在此处发出的查询类型。它的设计目的是在底层使用 map/reduce 来识别一定范围内的特定文档(小至 1 个文档的范围),而不是排除特定文档。您所要求的在 CouchBase 中不会有效。如果您的目标是有效地执行此类查询,那么您就使用了错误的技术。

但是,如果您束手无策并且被锁定在 CouchBase Lite 中,那么您就必须在您拥有的查询类型范围内工作。排除特定值可以重述为包括所有其他值。如果您想在 CouchBase 中执行此操作,则可以使用范围查询,其范围设计为不包含您要排除的值。

这是一个简短的概念示例。假设您的视图包含键为“A”、“B”、“C”、“D”、“F”和“X”的文档,并且您想要发出一个查询,其结果不包括文档“D”。您可以通过首先发出“A”-“C”的范围查询,然后发出“E”-“Z”的第二个范围查询来获得所需的结果。两个结果加起来就是除“D”之外的所有结果。

当然,这些都是简单的键。键越复杂,排除特定值的范围端点就越复杂。您想要排除的键越多,您必须执行的查询就越多(您必须对 N 个排除的术语执行 N + 1 次查询)。通过查询视图中的所有值并自己在代码中过滤它们,您可能会拥有一个更高效的系统。