[JAVA-4429] Updates push/addToSet Does Not Add Discriminator to Subdocuments Created: 18/Dec/21  Updated: 27/Oct/23  Resolved: 03/Feb/22

Status: Closed
Project: Java Driver
Component/s: Builders
Affects Version/s: None
Fix Version/s: None

Type: New Feature Priority: Unknown
Reporter: Mingze Wang Assignee: Ross Lawley
Resolution: Gone away Votes: 0
Labels: external-user
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
is related to JAVA-2720 Support Enums in query helpers Closed

 Description   

Summary

Updates push/addToSet Does Not Add Discriminator to Subdocuments

Please provide the version of the driver. If applicable, please provide the MongoDB server version and topology (standalone, replica set, or sharded cluster).

org.mongodb:mongodb-driver-sync:4.2.3

Mongo 4.4.10 running on Atlas

How to Reproduce

Say if we have the following objects:

public class HDUser {
 
  private ObjectId id;
 
  private List<Content> contents;
}

@BsonDiscriminator(value="Content", key="_cls")
public class Content {
  private ObjectId id;
  private Metadata metadata;
}

@BsonDiscriminator(value="Metadata", key="_cls")
public class Metadata {
  private String name;
  private Long size;
}

If I add a Content with Metadata to an existing HDUser, I expect that Metadata to have a field called "_cls: Metadata" however, I do not see that. Content would have its BsonDiscriminator, but not the subdocument (metadata) within it.

This is what I ran to add the content

Content c = new Content(...)
Bson addContent = Updates.addToSet("content", c);
Bson updateContentOrder = Updates.addToSet("content_order", c.getId());
return userCollection.updateOne(eq("_id", uid), Updates.combine(addContent, updateContentOrder));

 



 Comments   
Comment by PM Bot [ 03/Feb/22 ]

There hasn't been any recent activity on this ticket, so we're resolving it. Thanks for reaching out! Please feel free to comment on this if you're able to provide more information.

Comment by Ross Lawley [ 19/Jan/22 ]

Hi mizw2010@gmail.com,

Thanks for the ticket. I used the example and created the following:

import com.mongodb.MongoClientSettings;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Updates;
import org.bson.BsonDocument;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.codecs.pojo.PojoCodecProvider;
import org.bson.conversions.Bson;
import org.bson.types.ObjectId;
 
import java.util.Collections;
 
import static com.mongodb.client.model.Filters.eq;
import static org.bson.codecs.configuration.CodecRegistries.fromProviders;
import static org.bson.codecs.configuration.CodecRegistries.fromRegistries;
 
public class Main {
 
    public static void main(String[] args) throws InterruptedException {
 
        CodecRegistry codecRegistry = fromRegistries(MongoClientSettings.getDefaultCodecRegistry(),
                fromProviders(PojoCodecProvider.builder().automatic(true).build()));
 
        MongoClient mongoClient = MongoClients.create();
        MongoDatabase testDatabase = mongoClient.getDatabase("test").withCodecRegistry(codecRegistry);
        testDatabase.drop();
 
        MongoCollection<HDUser> userCollection = testDatabase.getCollection("user", HDUser.class);
        ObjectId uid = new ObjectId("000000000000000000000001");
        userCollection.insertOne(new HDUser().setId(uid).setContents(Collections.emptyList()));
 
        Content c = new Content().setId(new ObjectId("000000000000000000000000")).setMetadata(new Metadata().setName("name").setSize(42L));
        Bson addContent = Updates.addToSet("contents", c);  // Note: contents not content
 
        Bson updateContentOrder = Updates.addToSet("content_order", c.getId());  // Note: This field is not listed in the POJO!
        Bson combined = Updates.combine(addContent, updateContentOrder);
 
        System.out.println(combined.toBsonDocument(BsonDocument.class, codecRegistry));
 
        userCollection.updateOne(eq("_id", uid), Updates.combine(addContent, updateContentOrder));
 
        System.out.println(userCollection.find().first());
        System.out.println(testDatabase.getCollection("user").find().first().toJson());
    }
}

 

I used combined.toBsonDocument so I could see the converted operation as in its Bson form:

{"$addToSet": {"contents": {"_id": {"$oid": "000000000000000000000000"}, "_cls": "Content", "metadata": {"_cls": "Metadata", "name": "name", "size": 42}}, "content_order": {"$oid": "000000000000000000000000"}}}

That does have the _cls discriminator fields, I also added a toString method to the Pojos and outputted that as well as the extended json data:

HDUser{id=000000000000000000000001, contents=[Content{id=000000000000000000000000, metadata=Metadata{name='name', size=42}}]}
 
{"_id": {"$oid": "000000000000000000000001"}, "contents": [{"_id": {"$oid": "000000000000000000000000"}, "_cls": "Content", 
  "metadata": {"_cls": "Metadata", "name": "name", "size": 42}}], "content_order": [{"$oid": "000000000000000000000000"}]}

If I add a Content with Metadata to an existing HDUser, I expect that Metadata to have a field called "_cls: Metadata" however, I do not see that. Content would have its BsonDiscriminator, but not the subdocument (metadata) within it.

I haven't been able to reproduce that, I tested against 4.3.4, the latest 4.3 release and also on the latest release: 4.4.1

Please could you try running the example code above and let me know the output?

Ross

Comment by Esha Bhargava [ 21/Dec/21 ]

mizw2010@gmail.com Thank you for filing the issue! We'll look into it and get back to you soon.

Generated at Thu Feb 08 09:02:03 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.