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?