1

I'm wondering for best practices to upsert a document based on two identifiers.

@Document(collection = "cars")
public class CarEntity {
    @Id
    private ObjectId id;
    private String color;
    private String brand;
    private Instant repairedAt;
        ...
}

Each car is identifiable with the combination of color and brand, which is the logical ID to upsert a document. I want to update the repairedAt field.

Now there are (to my knowledge) three good ways to handle that.

Option 1: Custom repository with custom upsertOneByColorAndBrand which either

1.a) uses the CarRepository internally:

public void upsertOneByColorAndBrand(final CarEntity carNew,
                                           final String color,
                                           final String brand) {
    // findOneByColorAndBrand is no custom implementation, just from the interface
    var carExisting = repo.findOneByColorAndBrand(color, brand);
    if (carExisting == null) {
        // write to DB if not existent
        repo.save(carNew);
    } else {
        // update document if existing
        carExisting.setRepairedAt(carNew.getRepairedAt());
        repo.save(carExisting);
    }
}

1.b) or uses MongoTemplate internally:

public void upsertOneByColorAndBrand(final CarEntity carNew,
                                           final String color,
                                           final String brand) {
    // define find query
    Query query = new Query();
    query.addCriteria(Criteria.where("color").is(color));
    query.addCriteria(Criteria.where("brand").is(brand));

    // create document from entity
    Document doc = new Document();
    mongoTemplate.getConverter().write(carNew, doc);
    Update update = Update.fromDocument(doc);

    // upsert
    mongoTemplate.upsert(query, update, CarEntity.class);
}

Option 2: You could also skip the whole custom repository implementation and just define the ID of the document yourself, based on the combination of color & brand, as the combination of these are unique in this example. When doing that, you can just use the native repo.save(car), as it will automagically use the new composite ID to operate, which skips the whole "find" part.

I compared the performance of option 1.a and option 1.b and the difference is in the milliseconds for a three digit amount of documents. That's because 1.a) splits up the "find" and "save" operation.

Are there huge downsides/benefits with option 2? In your experience, is using a composite ID in the Spring Data environment a good idea? Would you rather use compound indexes or "set" the ID manually when creating the entity?

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.