Watch keynotes and sessions from MongoDB.live, our virtual developer conference.

UUID as primary key

Hi, I have problems setting my primary key ‘_id’ as UUID.
My DAO code:

package de.tudo.ls14.aqua.smarthome.dao;

import com.mongodb.ConnectionString;
import com.mongodb.MongoClientSettings;
import com.mongodb.client.*;

import static com.mongodb.client.model.Filters.eq;

import com.mongodb.client.model.FindOneAndReplaceOptions;
import com.mongodb.client.model.ReturnDocument;
import de.tudo.ls14.aqua.smarthome.model.Device;
import de.tudo.ls14.aqua.smarthome.model.Household;
import de.tudo.ls14.aqua.smarthome.model.User;
import org.bson.Document;
import org.bson.UuidRepresentation;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.codecs.pojo.PojoCodecProvider;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;

import static org.bson.codecs.configuration.CodecRegistries.fromProviders;
import static org.bson.codecs.configuration.CodecRegistries.fromRegistries;

@Repository("Mongodao")
public class MongoDao {
    final MongoClient mongoClient;
    final MongoDatabase mongoDatabase;
    final MongoCollection<User> userCollection;
    final MongoCollection<Household> householdCollection;
    final MongoCollection<Device> deviceCollection;


    public MongoDao() {
        String password = System.getProperty("password");//Passwort aus den VM options
        Logger.getLogger("org.mongodb.driver").setLevel(Level.ALL);
        ConnectionString connectionString = new ConnectionString("someConnectionString");
        CodecRegistry pojoCodecRegistry = fromProviders(PojoCodecProvider.builder().automatic(true).build());
        CodecRegistry codecRegistry = fromRegistries(MongoClientSettings.getDefaultCodecRegistry(), pojoCodecRegistry);
        MongoClientSettings clientSettings = MongoClientSettings.builder()
                .uuidRepresentation(UuidRepresentation.STANDARD)
                .applyConnectionString(connectionString)
                .codecRegistry(codecRegistry)
                .build();

        mongoClient = MongoClients.create(clientSettings);

        mongoDatabase = mongoClient.getDatabase("ProjektDB");
        userCollection = mongoDatabase.getCollection("userCollection", User.class);
        householdCollection = mongoDatabase.getCollection("householdCollection", Household.class);
        deviceCollection = mongoDatabase.getCollection("deviceCollection", Device.class);
    }

    public User getUserById(UUID id) {
        return userCollection.find(eq("id", id)).first();
    }

    public Household getHouseholdById(UUID id) {
        return householdCollection.find(eq("id", id)).first();
    }

    public Device getDeviceById(UUID id) {
        return deviceCollection.find(eq("id", id)).first();
    }

    public int addHousehold(Household household) {
        householdCollection.insertOne(household);
        return 1;
    }

    public int addUser(User user) {
        userCollection.insertOne(user);
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> added:"+user.toString());
        return 1;
    }

    public int addDevice(Device device) {
        deviceCollection.insertOne(device);
        return 1;
    }

    public User updateUserById(User user) {
        Document filterByUserId = new Document("_id", user.get_id());
        FindOneAndReplaceOptions returnDocAfterReplace = new FindOneAndReplaceOptions().returnDocument(ReturnDocument.AFTER);
        return userCollection.findOneAndReplace(filterByUserId, user, returnDocAfterReplace);
    }

    //nur zum testen
    public List<User> getAllUsers() {
        MongoCursor<User> cursor = userCollection.find().iterator();
        List<User> userList = new ArrayList<>();
        try{
            while(cursor.hasNext()){
                userList.add(cursor.next());
            }
        } finally {
            cursor.close();
        }
        return userList;
    }
}

I do not alter my POJO.
My POJO:

package de.tudo.ls14.aqua.smarthome.model;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class User {
    private String name;
    private UUID _id;
    private List<UUID> households;
    private String email;

    public User(){
        name = null;
        _id = null;
        households=null;
        email = null;
    }

    public User(UUID _id, String name, List<UUID> households, String email) {
        this._id = _id;
        this.name = name;
        this.households = households;
        this.email = email;
    }

    public String getName() {
        return name;
    }

    public User setName(String name) {
        this.name = name;
        return this;
    }

    public UUID get_id() {
        return _id;
    }

    public User set_id(UUID _id) {
        this._id = _id;
        return this;
    }

    public List<UUID> getHouseholds() {
        return households;
    }

    public User setHouseholds(List<UUID> households) {
        this.households = households;
        return this;
    }

    public String getEmail() {
        return email;
    }

    public User setEmail(String email) {
        this.email = email;
        return this;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", _id=" + _id +
                ", households=" + households +
                ", email='" + email + '\'' +
                '}';
    }
}

The _id field is UUID, but when i open atlas, it gives every user an Object_id.
How can i fix that?

Hello, Bruno! Welcome to the community! :wave:
In order we could help you, please provide:

  • example of a document in your collection
  • query or aggregation, that you use to get that document
  • what you expect for the result

Sorry about the big picture, can’t edit the post. There must’ve been a problem because I used a certain symbol

sure,
When I use postman I get:

{
    "name": "Bla Mcblub",
    "_id": null,
    "households": [
        "c0777af0-7a56-414b-a1dc-5e9ed567d4a7",
        "76d2635c-fe63-42d2-b6d0-866e7cd750e8"
    ],
    "email": "blamail@test.com"
}

As you can see the households perfectly hold the UUID, but the _id doesn’t.
In atlas it looks like this:

{"_id":{"$oid":“5ee4ea278324f83031afbda3”},“email":"blamail@test.com”,“households”:[{"$binary":{“base64”:“wHd68HpWQUuh3F6e1WfUpw==”,“subType”:“04”}},{"$binary":{“base64”:“dtJjXP5jQtK20IZufNdQ6A==”,“subType”:“04”}}],“name”:“Bla Mcblub”}

Again, there is clearly an objectid for the _id field which I don’t want and apparently postman can’t read that.

Just for the fun of it here a printout of the toString right before i push the object into the DB:

added:User{name=‘TotallyLegitName’, _id=05c17b25-4c78-49d8-bec0-12a4111f823e, households=[7acc98ef-30f0-4db4-a5df-e1faa6e38b85, 44b5499f-f00f-4e81-8d2b-a284a0c65436], email=‘totally@legit.com’}

I do actually have one idea of why it may occur. I might have posted two different users with the same _id at time point by accident, thus mongo wasn’t happy and maybe decided to do smthg about it (as every _id needs to be singular as im understanding it). But what to do about that?