Как получить java.util.Map из id в строку prop в couchdb, используя ektorp - PullRequest
3 голосов
/ 09 ноября 2011

У меня проблемы с тем, что я думаю, будет простой проблемой.По сути, мне нужен java.util.Map<String, String>, где идентификаторы в конечном итоге становятся ключами карты, а 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);
} 

Это уже очень уродливо, но на самом деле это не работает, так каккажется, что результаты JSON, которые возвращает queryForStream, включают случайные другие вещи, а не просто результат запроса.Это вызывает вызов readValue для выдачи IOException.

Я также пытался использовать reduce для генерации одного объекта, содержащего все эти значения, но в результате Couch жалуется на уменьшениенедостаточно сокращается ...

Ответы [ 2 ]

3 голосов
/ 11 ноября 2011

Я бы сделал что-то вроде этого:

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;
2 голосов
/ 09 ноября 2011

Вам нужно будет предварительно проанализировать вывод из CouchDB, так как нет способа избежать возврата всех этих метаданных с запросом.

Во-первых, ваше представление должно излучать правильные данные (идентификатор объекта и его значение).

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

Форма ответа - это объект JSONСтрока => Объект.Я хотел бы начать с отображения всего ответа на этот вопрос, а затем выбрать объект с ключом «строки», который является массивом 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 = false» через диван.

...