This exception:
Exception in thread \"Thread-1\" java.lang.IllegalArgumentException: Invalid BSON field name id
at org.bson.AbstractBsonWriter.writeName(
updateOne
for updating document fields using update operators. You need replaceOne
which takes the replacement document.
_collection.replaceOne(
trackID,
track,
new UpdateOptions().upsert( true ));
More here
Update Operators: https://docs.mongodb.com/manual/reference/operator/update-field/
Update One:https://docs.mongodb.com/manual/reference/method/db.collection.updateOne/
Replace One: https://docs.mongodb.com/manual/reference/method/db.collection.replaceOne/
Another option is setOnInsert
, as shown in the document of MongoDB:
https://docs.mongodb.com/manual/reference/operator/update/setOnInsert/
The operation works only when upsert
is true
.
In your case, you should put fields not to be modified in a document, and fields to be updated in another document, and in the third document, prepend $setOnInsert
and $set
as key, respectively.
A big advantage of $setOnInsert
is that when inserting, it will perform $setOnInsert
and $set
part, but when updating, only $set
will be executed.
For example, we have a document to insert/update, which has 5 fields: name
, age
, gender
, createAt
, updateAt
.
createAt
and updateAt
with current datetime.name
and updateAt
with current datetime.What I do is:
query = Filters.eq("name", nameToSearch);
Document upsert = new Document();
Date now = new Date();
//only fields not mentioned in "$set" is needed here
Document toInsert = new Document()
.append("age", newAge)
.append("gender", genderString)
.append("createAt", now);
//the fields to update here, whether on insert or on update.
Document toUpdate = new Document().append("name", nameToSearch)
.append("updateAt", now);
//will:
// - insert 5 fields if query returns no match
// - updates 2 fields if query returns match
upsert.append("$setOnInsert", toInsert)
.append("$set", toUpdate);
UpdateResult result = collection.updateOne(query, toUpdate,
new UpdateOptions().upsert(true));