3

我在处理我认为是一个简单的问题时遇到了麻烦。基本上,我需要一个java.util.Map<String, String>,其中 id 最终成为映射键,而someField我的文档最终出现在值中。

我真的很坚持这一点,这让我感到非常惊讶。我试过写一个单独的视图:

@View(map="function(d) { if (d.someField) { emit(d.someField, null); } }", name = "someField")

然后使用以下Java:

public Map<String, String> getSomeFields() throws JsonParseException, JsonMappingException, IOException {
    ViewQuery q = new ViewQuery().designDocId("_design/" + entity.getSimpleName()).viewName("someField");
    String result = StreamUtils.inputStreamAsString(db.queryForStream(q), false);
    TypeReference<Map<String, String>> mapTypeRef = new TypeReference<Map<String,String>>() {};
    // mapper is a Jackson ObjectMapper
    return mapper.readValue(result, mapTypeRef);
} 

这已经很丑陋了,但它实际上也不起作用,因为queryForStream返回的 JSON 结果似乎包括随机的其他内容,而不仅仅是查询的结果。这会导致readValue调用抛出一个IOException.

我也尝试过使用reduce来生成包含所有这些值的单个对象,但结果是 Couch 抱怨 reduce 减少得不够......

4

2 回答 2

3

我会做这样的事情:

ViewQuery query = ...

Map<String, String> map = new HashMap<String, String>();
for (ViewResult.Row row : db.queryView(query)) {
    map.put(row.getId(), row.getKey());
}

return map;
于 2011-11-11T16:03:39.920 回答
2

您需要预先解析 CouchDB 的输出,因为无法避免在查询中返回所有元数据。

首先,您的视图需要发出正确的数据(对象 ID 及其值)。

@View(map="function(d) { if (d.someField) { emit(d.id, d.someField); } }", name = "someField")

回复的形式是 JSON 对象 String => Object。我首先将整个回复映射到此,然后选择带有键“rows”的对象,该对象是一个 JSON 数组。此数组中的每个元素都是另一个 JSON 对象,键为“id”、“key”、“value”。然后,您需要将这些对象中的每一个映射到输出中的键值对。

public Map<String, String> getSomeFields() 
        throws JsonParseException, JsonMappingException, IOException {

    ViewQuery q = 
        new ViewQuery().designDocId("_design/" + 
        entity.getSimpleName()).viewName("someField");

    String queryRresult = 
        StreamUtils.inputStreamAsString(db.queryForStream(q), false);

    TypeReference<Map<String, Object>> mapTypeRef = 
        new TypeReference<Map<String,Object>>() {};

    TypeReference<List<Map<String,String>>> rowsTypeRef = 
        new TypeReference<List<Map<String,String>>>() {};

    // Map of the top level results which includes the couch meta and the
    // rows. We have to use object, because Each value is of a different 
    // type (string, ints, json objects)
    Map<String,Object> topResultMap = 
        mapper.readValue(queryRresult, mapTypeRef);

    // Once we have the top level result, cast the value for key "rows" as 
    // String, and parse it as a rows type, which is a list of maps.
    List<Map<String,String>> rows = 
        mapper.readValue((String) topResultMap.get("rows"), rowsTypeRef);

    // Finally iterator over that list pulling out the id and the value in 
    // the key and value for the results
    Map<String,String> results = new HashMap<String,String>();
    for (Map<String,String> row : rows)
        results.put(row.get("id"), row.get("value"));

    // And return them
    return results;
}

最后,您需要确保您的 CouchDB 视图中没有 reduce 部分。如果这样做,则必须将“reduce=false”传递给沙发。

于 2011-11-09T16:33:26.503 回答