sql >> Database >  >> NoSQL >> MongoDB

MongoDB BSON-codec wordt niet gebruikt tijdens het coderen van het object

Na een aantal dagen onderzoek heb ik een oplossing gevonden.

De DutyBlockCodec hangt af van de LocalDateCodec (die ik heb gemaakt) om te coderen / decoderen. Aan deze afhankelijkheid wordt niet voldaan door de twee codecs toe te voegen aan hetzelfde codec-register. De oplossing is om een ​​CodecRegistry . door te geven object dat de codecs bevat die DutyBlockCodec hangt af van (bijvoorbeeld een CodecRegistry met daarin de LocalDateCodec ) naar de DutyBlockCodec 's constructor, die wordt opgeslagen als een lidvariabele. Om de LocalDateCodec . te gebruiken om te coderen, gebruik ik de EncoderContext.encodeWithChildContext() methode, waarbij de codec, de schrijver en het te coderen element worden doorgegeven. Bovendien schrijf ik individuele velden in plaats van een Document als een String (zoals in mijn originele code). Dus de DutyBlock codec ziet er uiteindelijk zo uit:

public class DutyBlockCodec implements Codec<DutyBlock> {
    private final CodecRegistry codecRegistry;

    public DutyBlockCodec(final CodecRegistry codecRegistry) {
        this.codecRegistry = codecRegistry;
    }

    @Override
    public void encode(BsonWriter writer, DutyBlock t, EncoderContext ec) {
        writer.writeStartDocument();
            Codec dateCodec = codecRegistry.get(LocalDate.class);
            writer.writeName("startDate");
            ec.encodeWithChildContext(dateCodec, writer, t.getStartDate());
            writer.writeName("endDate");
            ec.encodeWithChildContext(dateCodec, writer, t.getEndDate());
            writer.writeName("blockLength");
            writer.writeInt32(t.getBlockLength());
            writer.writeName("pointValue");
            writer.writeDouble(t.getPointValue());

            //Writing ArrayList of RAs
            writer.writeName("assigned");
            writer.writeStartArray();
                for (Ra ra : t.getRasOnDuty()) {
                    Codec raCodec = codecRegistry.get(Ra.class);
                    ec.encodeWithChildContext(raCodec, writer, ra);
                }
            writer.writeEndArray();
        writer.writeEndDocument();
    }

    @Override
    public Class<DutyBlock> getEncoderClass() {
        return DutyBlock.class;
    }

    @Override
    public DutyBlock decode(BsonReader reader, DecoderContext dc) {
        reader.readStartDocument();
            Codec<LocalDate> dateCodec = codecRegistry.get(LocalDate.class);
            reader.readName();
            LocalDate startDate = dateCodec.decode(reader, dc);
            reader.readName();
            LocalDate endDate = dateCodec.decode(reader, dc);
            reader.readName();
            int blockLength = reader.readInt32();
            reader.readName();
            double pointValue = reader.readDouble();

            //Reading ArrayList of RAs
            reader.readName();
            Codec<Ra> raCodec = codecRegistry.get(Ra.class);
            ArrayList<Ra> rasOnDuty = new ArrayList<>();
            reader.readStartArray();
                while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) {
                    rasOnDuty.add(raCodec.decode(reader, dc));
                }
            reader.readEndArray();
        reader.readEndDocument();

        return new DutyBlock(startDate, endDate, blockLength, pointValue, rasOnDuty);
    }

}

DutyBlockCodec hangt af van een andere codec, en vereist dus een CodecRegistry door te geven aan de constructeur. Hoewel ik geloof dat het mogelijk is om een ​​CodecRegistry . te maken met de LocalDateCodec , geef dit dan als argument door aan DutyBlockCodec 's constructor, maak dan nog een CodecRegistry met zowel LocalDateCodec en DutyBlockCodec , dit is nogal verwarrend, en MongoDB biedt een functionaliteit, de CodecProvider om dit proces te vergemakkelijken.

De CodecProvider gebruiken interface, schreef ik een DutyBlockCodecProvider

public class DutyBlockCodecProvider implements CodecProvider {
    @Override
    public <T> Codec<T> get(Class<T> type, CodecRegistry cr) {
        if (type == DutyBlock.class) {
            return (Codec<T>) new DutyBlockCodec(cr);
        }
        return null;
    }
}

Ik heb deze CodecProviders toegevoegd naar de MongoDB-client met behulp van de CodecRegistries.fromProviders() methode.

CodecRegistry codecRegistry = CodecRegistries.fromRegistries(
            CodecRegistries.fromCodecs(new LocalDateCodec()),
            CodecRegistries.fromProviders(
                    new RaCodecProvider(),
                    new DutyBlockCodecProvider(),
                    new ScheduledDutyCodecProvider()),
            MongoClient.getDefaultCodecRegistry());  
    MongoClientOptions options = MongoClientOptions.builder()
            .codecRegistry(codecRegistry).build();
    mongoClient = new MongoClient(new ServerAddress(), options);
    db = mongoClient.getDatabase("DutySchedulerDB");

Mijn broncode voor dit project is te vinden op https://github.com/desrepair/DutyScheduler. Ik sta open voor het beantwoorden van alle vragen die mensen hebben.



  1. MongoDB Single Document-limiet is 16 MB

  2. mongoexport E QUERY SyntaxError:Onverwachte id

  3. Is het mogelijk om dynamisch benoemde MongoDB-verzamelingen te genereren?

  4. Wat is MapReduce Key Value Pair in Hadoop?