MongoDB的Java驱动程序会将嵌套对象的id字段转换为_id。

huangapple go评论72阅读模式
英文:

MongoDB Java driver converts id field of nested object into _id

问题

以下是翻译好的内容:

我有一个嵌套对象,其中定义了一个名为 id 的字段,但在持久化到 mongodb 时会转换为 _id。我正在尝试避免这种情况,因为嵌套对象的 id 字段不是一个 ObjectId。

这里有两个简单的 POJO 实体:

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;
}

这是我正在使用 mongodb java 驱动程序创建租户并持久化的示例方式。

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();
}

由于这个插入操作,appClient 的字段 _id 会代替 id

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

这在按 id 搜索内部文档时会引发问题。因此,在上面的示例中,findResult 将为 null,因为没有定义任何 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(&quot;mongodb://127.0.0.1:27017&quot;);
        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&lt;Tenant&gt; mongoCollection = mongoClient.getDatabase(&quot;alpha&quot;).getCollection(&quot;tenant&quot;, Tenant.class);

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

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

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

{ &quot;_id&quot; : ObjectId(&quot;5f4a80b4a0bf93152208e210&quot;), &quot;appClient&quot; : { &quot;_id&quot; : &quot;12312313&quot; } }

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!

答案1

得分: 0

只是发现 MongoDB Java 驱动程序将每个以 id 命名的字段默认更改为 _id。因此,解决方法是更改 ANNOTATION_CONVENTION 的默认约定类型,如下所示:

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

此外,我们必须使用 BsonId 注释 id 字段,该字段是一个 ObjectId。我们的 Tenant POJO 将如下所示:

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

相关行为在 https://jira.mongodb.org/browse/JAVA-2750 中有解释。

英文:

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

huangapple
  • 本文由 发表于 2020年8月30日 00:30:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/63649322.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定