来自Ektorp的CouchDB Map / Reduce视图查询

时间:2012-09-13 14:59:13

标签: nosql mapreduce couchdb

我正在尝试根据我在CouchDB上创建的Map / Reduce视图从java执行查询。 我的地图功能如下所示:

function(doc) {
  if(doc.type == 'SPECIFIC_DOC_TYPE_NAME' && doc.userID){
    for(var g in doc.groupList){
        emit([doc.userID,doc.groupList[g].name],1);
    }
  }
}

和Reduce功能:

  function (key, values, rereduce) {
        return sum(values); 
}

从Futon界面执行时,视图似乎正常工作(尽管没有指定键)。 我要做的是计算属于单个组的某些doc类型的数量。我想使用'userID'和组的名称作为键来查询该视图。

我正在使用Ektorp库来管理CouchDB数据,如果我在没有键的情况下执行此查询它会返回标量值,否则它只会输出一个错误,说明对于reduce query group = true必须指定。

我尝试了以下内容:

ViewQuery query = createQuery("some_doc_name");
        List<String> keys = new ArrayList<String>();
        keys.add(grupaName);
        keys.add(uzytkownikID);
        query.group(true);
        query.groupLevel(2);
        query.dbPath(db.path());
        query.designDocId(stdDesignDocumentId);
        query.keys(keys);
        ViewResult r = db.queryView(query);
        return r.getRows().get(0).getValueAsInt();

以上示例在没有指定“键”的情况下工作。 我有其他查询使用ComplexKey,例如:

ComplexKey key = ComplexKey.of(userID);
return queryView("list_by_userID",key);

但是这只返回T(List)类型的列表 - 当然使用CouchDbRepositorySupport - 并且不能与reduce类型查询一起使用(据我所知)。

有没有办法使用指定的reduce函数执行查询,使用Ektorp库执行具有2个或更多值的复杂键?任何例子都高度赞赏。

2 个答案:

答案 0 :(得分:3)

除了克里斯的回答:

请注意,当您要查询文档 一组密钥以查找文档时,会使用ViewQuery.keys() (s)带有复杂的钥匙。

与Kris的回答一样,以下示例将获得与指定的“键”)匹配的文档

viewQuery.key("hello");                             // simple key
viewQuery.key(documentSlug);                        // simple key
viewQuery.key(new String[] { userID, groupName });  // complex key, using array
viewQuery.key(ComplexKey.of(userID, groupName));    // complex key, using ComplexKey

另一方面,以下示例将获得与指定匹配的文档,其中每个键可以是简单键或复杂键:

// simple key: in essence, same as using .key()
viewQuery.keys(ImmutableSet.of("hello"));
viewQuery.keys(ImmutableSet.of(documentSlug1));
// simple keys
viewQuery.keys(ImmutableSet.of("hello", "world"));
viewQuery.keys(ImmutableSet.of(documentSlug1, documentSlug2));
// complex key: in essence, same as using .key()
viewQuery.keys(ImmutableSet.of(
    new String[] { "hello", "world" } ));
viewQuery.keys(ImmutableSet.of(
    new String[] { userID1, groupName1 } ));
// complex keys
viewQuery.keys(ImmutableSet.of(
    new String[] { "hello", "world" },
    new String[] { "Mary", "Jane" } ));
viewQuery.keys(ImmutableSet.of(
    new String[] { userID1, groupName1 },
    new String[] { userID2, groupName2 } ));
// a simple key and a complex key. while technically possible,
// I don't think anybody actually does this
viewQuery.keys(ImmutableSet.of(
    "hello",
    new String[] { "Mary", "Jane" } ));

注意:ImmutableSet.of()来自guava library

new Object[] { ... }似乎与ComplexKey.of( ... )

具有相同的行为

此外,还有startKey()endKey()用于使用部分密钥进行查询。 要发送空对象{},请使用ComplexKey.emptyObject()。 (仅对部分密钥查询有用)

答案 1 :(得分:2)

好的,我找到了使用试错法的解决方案:

public int getNumberOfDocsAssigned(String userID, String groupName) {
        ViewQuery query = createQuery("list_by_userID")
                .group(true)
                .dbPath(db.path())
                .designDocId(stdDesignDocumentId)
                .key(new String[]{userID,groupName});
        ViewResult r = db.queryView(query);
        return r.getRows().get(0).getValueAsInt();
    }

因此,关键是要将复杂密钥不是密钥)实际发送为包含字符串的单个(但复杂)密钥数组,由于某种原因'.keys(...)'对我来说不起作用(它需要一个Collection作为参数)。 (有关.key().keys()之间差异的解释,请参阅Hendy的回答)

此方法计算分配给特定用户(由'userID'指定)和特定组(由'groupName'指定)的所有文档。

希望能帮助任何人执行map / reduce查询,以便使用Ektorp查询从CouchDB中检索标量值。