在MongoDB/Morphia中检索数组?

在MongoDB/Morphia中检索数组?,mongodb,morphia,Mongodb,Morphia,我想在MongodDB中以以下格式存储文档: { "_id" : ObjectId("563f904cd2a56e3934484c52"), "data" : [ [ "Year", "Profit" ], [ "2015", 2 ] ] } 我已经创建了一个POJO来适应这个结构 import or

我想在MongodDB中以以下格式存储文档:

{
    "_id" : ObjectId("563f904cd2a56e3934484c52"),
    "data" : [ 
        [ 
            "Year", 
            "Profit"
        ], 
        [ 
            "2015", 
            2
        ]
    ]
}
我已经创建了一个POJO来适应这个结构

import org.bson.types.ObjectId;
import org.mongodb.morphia.annotations.Entity;
import org.mongodb.morphia.annotations.Id;

import java.util.List;


@Entity(noClassnameStored = true)
public class Document {
    @Id
    private ObjectId id;
    private List<List<Object>> data;

    public ObjectId getId() {
        return id;
    }

    public void setId(ObjectId id) {
        this.id = id;
    }

    public List<List<Object>> getData() {
        return data;
    }

    public void setData(List<List<Object>> data) {
        this.data = data;
    }
}
我得到以下例外情况:

java.lang.RuntimeException: java.lang.RuntimeException: java.lang.ClassCastException: java.lang.String cannot be cast to com.mongodb.DBObject
    at org.mongodb.morphia.mapping.EmbeddedMapper.fromDBObject(EmbeddedMapper.java:173)
    at org.mongodb.morphia.mapping.Mapper.readMappedField(Mapper.java:642)
    at org.mongodb.morphia.mapping.Mapper.fromDb(Mapper.java:617)
    at org.mongodb.morphia.mapping.Mapper.fromDBObject(Mapper.java:310)
    at org.mongodb.morphia.query.MorphiaIterator.convertItem(MorphiaIterator.java:87)
    at org.mongodb.morphia.query.MorphiaIterator.processItem(MorphiaIterator.java:73)
    at org.mongodb.morphia.query.MorphiaIterator.next(MorphiaIterator.java:68)
    at org.mongodb.morphia.query.QueryImpl.get(QueryImpl.java:421)

是否有方法将数据检索为
列表

在我的案例中,我为此创建了一个转换器,例如:

import com.mongodb.BasicDBObject;
import org.bson.types.BasicBSONList;
import org.mongodb.morphia.converters.TypeConverter;
import org.mongodb.morphia.mapping.MappedField;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class MyCustomDataConverter extends TypeConverter {
    @Override
    public Object decode(Class<?> targetClass, Object fromDBObject, MappedField optionalExtraInfo) {
        BasicDBObject obj = (BasicDBObject) fromDBObject;

        BasicBSONList colsArr = (BasicBSONList) obj.get("cols");
        List<String> cols = colsArr.stream()
                .map(c -> (String) c)
                .collect(Collectors.toList());

        BasicBSONList rowsArr = (BasicBSONList) obj.get("rows");
        List<List<?>> rows = rowsArr.stream()
                .map(rowObj -> (BasicBSONList) rowObj)
                .map(ArrayList::new)
                .collect(Collectors.toList());

        return new MyCustomData(cols, rows);
    }

    @Override
    public Object encode(Object value, MappedField optionalExtraInfo) {
        MyCustomData data = (MyCustomData) value;

        BasicDBObject obj = new BasicDBObject();
        obj.put("cols", list(data.columns()));

        BasicBSONList rowsObj = new BasicBSONList();
        for (List<?> row : data.data()) {
            rowsObj.add(list(row));
        }
        obj.put("rows", rowsObj);

        return obj;
    }

    private BasicBSONList list(List<?> elements) {
        BasicBSONList list = new BasicBSONList();
        list.addAll(elements);
        return list;
    }

    @Override
    protected boolean isSupported(Class<?> c, MappedField optionalExtraInfo) {
        return c == MyCustomData.class;
    }
}

我认为您不能使用
对象的列表,您需要使用更具体的内容,即(1)Morphia默认识别的类型(即
String
int
,等等),或(2)通过注释定义的实体。
java.lang.RuntimeException: java.lang.RuntimeException: java.lang.ClassCastException: java.lang.String cannot be cast to com.mongodb.DBObject
    at org.mongodb.morphia.mapping.EmbeddedMapper.fromDBObject(EmbeddedMapper.java:173)
    at org.mongodb.morphia.mapping.Mapper.readMappedField(Mapper.java:642)
    at org.mongodb.morphia.mapping.Mapper.fromDb(Mapper.java:617)
    at org.mongodb.morphia.mapping.Mapper.fromDBObject(Mapper.java:310)
    at org.mongodb.morphia.query.MorphiaIterator.convertItem(MorphiaIterator.java:87)
    at org.mongodb.morphia.query.MorphiaIterator.processItem(MorphiaIterator.java:73)
    at org.mongodb.morphia.query.MorphiaIterator.next(MorphiaIterator.java:68)
    at org.mongodb.morphia.query.QueryImpl.get(QueryImpl.java:421)
import com.mongodb.BasicDBObject;
import org.bson.types.BasicBSONList;
import org.mongodb.morphia.converters.TypeConverter;
import org.mongodb.morphia.mapping.MappedField;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class MyCustomDataConverter extends TypeConverter {
    @Override
    public Object decode(Class<?> targetClass, Object fromDBObject, MappedField optionalExtraInfo) {
        BasicDBObject obj = (BasicDBObject) fromDBObject;

        BasicBSONList colsArr = (BasicBSONList) obj.get("cols");
        List<String> cols = colsArr.stream()
                .map(c -> (String) c)
                .collect(Collectors.toList());

        BasicBSONList rowsArr = (BasicBSONList) obj.get("rows");
        List<List<?>> rows = rowsArr.stream()
                .map(rowObj -> (BasicBSONList) rowObj)
                .map(ArrayList::new)
                .collect(Collectors.toList());

        return new MyCustomData(cols, rows);
    }

    @Override
    public Object encode(Object value, MappedField optionalExtraInfo) {
        MyCustomData data = (MyCustomData) value;

        BasicDBObject obj = new BasicDBObject();
        obj.put("cols", list(data.columns()));

        BasicBSONList rowsObj = new BasicBSONList();
        for (List<?> row : data.data()) {
            rowsObj.add(list(row));
        }
        obj.put("rows", rowsObj);

        return obj;
    }

    private BasicBSONList list(List<?> elements) {
        BasicBSONList list = new BasicBSONList();
        list.addAll(elements);
        return list;
    }

    @Override
    protected boolean isSupported(Class<?> c, MappedField optionalExtraInfo) {
        return c == MyCustomData.class;
    }
}
import java.util.List;

public class MyCustomData {
    private final List<String> columns;
    private final List<List<?>> data;
    private MyCustomData() { // For Morphia
        this(null, null);
    }
    public MyCustomData(List<String> columns, List<List<?>> data) {
        this.columns = columns;
        this.data = data;
    }
    public List<String> columns() {
        return columns;
    }
    public List<List<?>> data() {
        return data;
    }
}
Morphia morphia = new Morphia();
morphia.getMapper().getConverters().addConverter(new MyCustomDataConverter() );