Search code examples
javamongodbmongodb-java

MongoDB Java driver converts id field of nested object into _id


I have a nested object with an id field defined which is converted as _id when persisting into mongodb. I am trying to avoid this since the nested object's id field is not an ObjectId.

Here are two simple POJO entities I have;

Tenant.java

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Tenant {

    private ObjectId id;
    private AppClient appClient;
    private Date createdAt;
}

AppClient.java

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class AppClient {
    private String id;
    private String secret;
    private String role;
}

And this is the example way I am creating a tenant and persisting with mongodb java driver.

public class MainTest {
    public static void main(String[] args) {
        ConnectionString connString = new ConnectionString("mongodb://127.0.0.1:27017");
        CodecRegistry pojoCodecRegistry = fromProviders(PojoCodecProvider.builder().automatic(true).build());
        CodecRegistry codecRegistry = fromRegistries(MongoClientSettings.getDefaultCodecRegistry(), pojoCodecRegistry);

        MongoClientSettings settings = MongoClientSettings.builder()
            .applyConnectionString(connString)
            .codecRegistry(codecRegistry)
            .build();

        MongoClient mongoClient = MongoClients.create(settings);
        MongoCollection<Tenant> mongoCollection = mongoClient.getDatabase("alpha").getCollection("tenant", Tenant.class);

        Tenant tenant = new Tenant();
        AppClient appClient = new AppClient();
        appClient.setId("12312313");
        tenant.setAppClient(appClient);

        mongoCollection.insertOne(tenant);
        Tenant findResult = mongoCollection.find(new Document().append("appClient.id", "12312313")).first();
}

As a result of this insert appClient has _id field instead of id.

{ "_id" : ObjectId("5f4a80b4a0bf93152208e210"), "appClient" : { "_id" : "12312313" } }

This causing an issue when searching inner documents by id. So, in the above example findResult will be null since there is no any id field defined. I appreciate for your help. Thanks anyway!


Solution

  • Just found that mongodb java driver defaults every field named with id to _id. So, the workaround was changing the default convention type of ANNOTATION_CONVENTION as shown below;

    PojoCodecProvider.builder().conventions(asList(Conventions.ANNOTATION_CONVENTION)).automatic(true).build();
    

    Additionally, we have to annotate id field which is an ObjectId with BsonId. Our Tenant POJO will looke like;

    
    @Getter
    @Setter
    @AllArgsConstructor
    @NoArgsConstructor
    public class Tenant {
        @BsonId
        private ObjectId id;
        private AppClient appClient;
        private Date createdAt;
    }
    

    The related behavior is explained at https://jira.mongodb.org/browse/JAVA-2750