java - 从 Mongo 文档中过滤 YearMonth

标签 java mongodb

在我的 MongoDB 文档中,json 如下所示

{ "_id" : ObjectId("582258c899f8b36081979d1b"), "customer" : "company-name", "start" : { "year" : 2016, "month" : 11 }, "end" : { "year" : 2016, "month" : 11 }

现在我想通过与 java 代码中的 YearMonth 变量进行比较来过滤掉“start”字段,所以我这样做了

public ContractDTO findContractFor(String customer, YearMonth period) {
    BasicDBObject query = new BasicDBObject();
    query.put("start", new BasicDBObject("$eq", period));
    MongoCollection<Document> collection = database.getCollection("contract");
    FindIterable<Document> documents = collection.find(query);
    Document first = documents.first();

执行上面最后一行时,出现以下异常

org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class java.time.YearMonth.
    at org.bson.codecs.configuration.CodecCache.getOrThrow(CodecCache.java:46)
    at org.bson.codecs.configuration.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:63)
    at org.bson.codecs.configuration.ChildCodecRegistry.get(ChildCodecRegistry.java:51)
    at com.mongodb.DBObjectCodec.writeValue(DBObjectCodec.java:210)
    at com.mongodb.DBObjectCodec.encodeMap(DBObjectCodec.java:220)
    at com.mongodb.DBObjectCodec.writeValue(DBObjectCodec.java:196)
    at com.mongodb.DBObjectCodec.encode(DBObjectCodec.java:128)
    at com.mongodb.DBObjectCodec.encode(DBObjectCodec.java:61)
    at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:63)
    at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:29)
    at org.bson.codecs.EncoderContext.encodeWithChildContext(EncoderContext.java:91)
    at org.bson.codecs.BsonDocumentCodec.writeValue(BsonDocumentCodec.java:133)
    at org.bson.codecs.BsonDocumentCodec.encode(BsonDocumentCodec.java:112)
    at org.bson.codecs.BsonDocumentCodec.encode(BsonDocumentCodec.java:40)
    at com.mongodb.connection.RequestMessage.addDocument(RequestMessage.java:253)
    at com.mongodb.connection.RequestMessage.addDocument(RequestMessage.java:205)
    at com.mongodb.connection.CommandMessage.encodeMessageBodyWithMetadata(CommandMessage.java:75)
    at com.mongodb.connection.RequestMessage.encodeWithMetadata(RequestMessage.java:160)
    at com.mongodb.connection.CommandProtocol.sendMessage(CommandProtocol.java:192)
    at com.mongodb.connection.CommandProtocol.execute(CommandProtocol.java:111)
    at com.mongodb.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:159)
    at com.mongodb.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:286)
    at com.mongodb.connection.DefaultServerConnection.command(DefaultServerConnection.java:173)
    at com.mongodb.operation.CommandOperationHelper.executeWrappedCommandProtocol(CommandOperationHelper.java:215)
    at com.mongodb.operation.CommandOperationHelper.executeWrappedCommandProtocol(CommandOperationHelper.java:206)
    at com.mongodb.operation.CommandOperationHelper.executeWrappedCommandProtocol(CommandOperationHelper.java:112)
    at com.mongodb.operation.FindOperation$1.call(FindOperation.java:487)
    at com.mongodb.operation.FindOperation$1.call(FindOperation.java:482)
    at com.mongodb.operation.OperationHelper.withConnectionSource(OperationHelper.java:239)
    at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:212)
    at com.mongodb.operation.FindOperation.execute(FindOperation.java:482)
    at com.mongodb.operation.FindOperation.execute(FindOperation.java:79)
    at com.mongodb.Mongo.execute(Mongo.java:772)
    at com.mongodb.Mongo$2.execute(Mongo.java:759)
    at com.mongodb.FindIterableImpl$FindOperationIterable.first(FindIterableImpl.java:207)
    at com.mongodb.FindIterableImpl.first(FindIterableImpl.java:148)

通过查看文档我无法弄清楚如何让它发挥作用。如果能得到某个方向的提示,我们将不胜感激。

最佳答案

您需要为年月创建自定义编解码器,因为这不是标准 Bson 类型。这涉及两个步骤。根据您的需要进行调整。

创建编解码器

public class YearMonthCodec implements Codec<YearMonth> {

    public void encode(BsonWriter writer, YearMonth value, EncoderContext encoderContext) {

        writer.writeStartDocument();

        writer.writeName("year");
        writer.writeInt32(value.getYear());
        writer.writeName("month");
        writer.writeInt32(value.getMonth().getValue());

        writer.writeEndDocument();

    }

    public Class<YearMonth> getEncoderClass() {
        return YearMonth.class;
    }

    public YearMonth decode(BsonReader reader, DecoderContext decoderContext) {

        reader.readStartDocument();

        int year = reader.readInt32("year");
        int month = reader.readInt32("month");

        reader.readEndDocument();

        return YearMonth.of(year, month);

    }

}   

向 Mongo 客户端注册编解码器

CodecRegistry codecRegistry = CodecRegistries.fromRegistries(CodecRegistries.fromCodecs(new YearMonthCodec()),
        MongoClient.getDefaultCodecRegistry());
MongoClientOptions options = MongoClientOptions.builder().codecRegistry(codecRegistry).build();
MongoClient mongoClient = new MongoClient(new ServerAddress(), options);

关于java - 从 Mongo 文档中过滤 YearMonth,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40516987/

相关文章:

java - 继承层次结构对泛型的限制是什么?

java - 属性文件中的 boolean 值

java - Excel 输出的第二列值放错位置

java - 如何使用 Jackcess 在 Access .mdb 中创建 ODBC 链接表?

javascript - Meteor 中的自动 createdAt 和 updatedAt 字段

java - 创建aar文件并进行检查

mongodb - 如何通过 Spark 查询 MongoDB 进行地理空间查询

mongodb - GridFS 和标准集合、内存使用

java - mongodb 尝试在更新中编辑 _id 字段时抛出错误

mongodb - 插入到 mongodb 集合的顶部