4

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

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

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

如果我写

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

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

但是我找不到一种简单的方法来编写排除(省略)具有某些键的文档的查询(例如与 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;
}

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

因此,您需要为他们想要省略的每个键创建新视图。但是,如果您有很多要排除的键或经常这样做,那将是低效的和样板的。

你知道任何更好的解决方案或黑客吗?

任何帮助表示
感谢提前感谢

4

1 回答 1

4

CouchBase 不适用于您要在此处发出的查询类型。它旨在在后台使用 map/reduce 来识别具有范围的特定文档(低至 1 个文档的范围),而不是排除特定文档。您要问的内容在 CouchBase 中不会有效。如果您的目标是有效地执行这些类型的查询,那么您就使用了错误的技术。

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

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

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

于 2014-08-03T16:19:13.483 回答