[英]MongoDb upsert exception invalid BSON field
This exception: 这个例外:
Exception in thread "Thread-1" java.lang.IllegalArgumentException: Invalid BSON field name id
at org.bson.AbstractBsonWriter.writeName(AbstractBsonWriter.java:516)
at org.bson.codecs.DocumentCodec.writeMap(DocumentCodec.java:188)
at org.bson.codecs.DocumentCodec.encode(DocumentCodec.java:131)
at org.bson.codecs.DocumentCodec.encode(DocumentCodec.java:45)
at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:63)
at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:29)
at com.mongodb.connection.UpdateCommandMessage.writeTheWrites(UpdateCommandMessage.java:85)
at com.mongodb.connection.UpdateCommandMessage.writeTheWrites(UpdateCommandMessage.java:43)
at com.mongodb.connection.BaseWriteCommandMessage.encodeMessageBodyWithMetadata(BaseWriteCommandMessage.java:129)
at com.mongodb.connection.RequestMessage.encodeWithMetadata(RequestMessage.java:160)
at com.mongodb.connection.WriteCommandProtocol.sendMessage(WriteCommandProtocol.java:220)
at com.mongodb.connection.WriteCommandProtocol.execute(WriteCommandProtocol.java:101)
at com.mongodb.connection.UpdateCommandProtocol.execute(UpdateCommandProtocol.java:64)
at com.mongodb.connection.UpdateCommandProtocol.execute(UpdateCommandProtocol.java:37)
at com.mongodb.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:168)
at com.mongodb.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:289)
at com.mongodb.connection.DefaultServerConnection.updateCommand(DefaultServerConnection.java:143)
at com.mongodb.operation.MixedBulkWriteOperation$Run$3.executeWriteCommandProtocol(MixedBulkWriteOperation.java:490)
at com.mongodb.operation.MixedBulkWriteOperation$Run$RunExecutor.execute(MixedBulkWriteOperation.java:656)
at com.mongodb.operation.MixedBulkWriteOperation$Run.execute(MixedBulkWriteOperation.java:409)
at com.mongodb.operation.MixedBulkWriteOperation$1.call(MixedBulkWriteOperation.java:177)
at com.mongodb.operation.MixedBulkWriteOperation$1.call(MixedBulkWriteOperation.java:168)
at com.mongodb.operation.OperationHelper.withConnectionSource(OperationHelper.java:422)
at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:413)
at com.mongodb.operation.MixedBulkWriteOperation.execute(MixedBulkWriteOperation.java:168)
at com.mongodb.operation.MixedBulkWriteOperation.execute(MixedBulkWriteOperation.java:74)
at com.mongodb.Mongo.execute(Mongo.java:845)
at com.mongodb.Mongo$2.execute(Mongo.java:828)
at com.mongodb.MongoCollectionImpl.executeSingleWriteRequest(MongoCollectionImpl.java:550)
at com.mongodb.MongoCollectionImpl.update(MongoCollectionImpl.java:542)
at com.mongodb.MongoCollectionImpl.updateOne(MongoCollectionImpl.java:381)
at org.hpms.gis.MongoDbTest.insert(MongoDbTest.java:63)
at java.lang.Thread.run(Thread.java:748)
is thrown by the following code: 由以下代码抛出:
final UUID id = UUID.randomUUID();
final double frequency = 8_000.0 + ( 10_000.0 * Math.random() );
final double startSec = 100*i;
final double startNano = 10*i;
final double endSec = startSec + ( 100*i );
final double endNano = startNano + ( 10*i );
final double latitude = ( 180.0*Math.random() ) - 90.0;
final double longitude = ( 360.0*Math.random() ) - 180.0;
final Document trackID = new Document(
"id", new Document(
"msb", id.getMostSignificantBits ()) .append(
"lsb", id.getLeastSignificantBits()));
final Document track = new Document(
"id", new Document(
"msb", id.getMostSignificantBits ()) .append(
"lsb", id.getLeastSignificantBits())).append(
"frequency", frequency ) .append(
"start", new Document(
"seconds", startSec ) .append(
"nanoSec", startNano )).append(
"end", new Document(
"seconds", endSec ) .append(
"nanoSec", endNano )).append(
"position", new Document(
"latitude" , latitude ) .append(
"longitude", longitude )).append(
"padding", new byte[1000-8-8-8-4-4-4-4-8-8] );
//_collection.insertOne( track );
_collection.updateOne(
trackID,
track,
new UpdateOptions().upsert( true ));
The commented code _collection.insertOne( track );
注释代码
_collection.insertOne( track );
executes fine. 执行得很好。
Why the insert is fine when the "upsert" is not? 为什么插入没有“upsert”?
updateOne
for updating document fields using update operators. updateOne
用于使用更新运算符更新文档字段。 You need replaceOne
which takes the replacement document. 您需要替换文档的
replaceOne
。
_collection.replaceOne(
trackID,
track,
new UpdateOptions().upsert( true ));
More here 更多这里
Update Operators: https://docs.mongodb.com/manual/reference/operator/update-field/ 更新运算符: https : //docs.mongodb.com/manual/reference/operator/update-field/
Update One: https://docs.mongodb.com/manual/reference/method/db.collection.updateOne/ 更新一: https : //docs.mongodb.com/manual/reference/method/db.collection.updateOne/
Replace One: https://docs.mongodb.com/manual/reference/method/db.collection.replaceOne/ 替换一个: https : //docs.mongodb.com/manual/reference/method/db.collection.replaceOne/
Another option is setOnInsert
, as shown in the document of MongoDB: 另一个选项是
setOnInsert
,如MongoDB文档中所示:
https://docs.mongodb.com/manual/reference/operator/update/setOnInsert/ https://docs.mongodb.com/manual/reference/operator/update/setOnInsert/
The operation works only when upsert
is true
. 仅当
upsert
为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. 在您的情况下,您应该在文档中放置不要修改的字段,在另一个文档中放置要更新的字段,在第三个文档中,分别
$set
$setOnInsert
和$set
作为键。
A big advantage of $setOnInsert
is that when inserting, it will perform $setOnInsert
and $set
part, but when updating, only $set
will be executed. $setOnInsert
一大优点是,在插入时,它将执行$setOnInsert
和 $set
part,但是在更新时,只会执行$set
。
For example, we have a document to insert/update, which has 5 fields: name
, age
, gender
, createAt
, updateAt
. 例如,我们有一个要插入/更新的文档,它有5个字段:
name
, age
, gender
, createAt
, updateAt
。
createAt
and updateAt
with current datetime. createAt
和updateAt
。 name
and updateAt
with current datetime. name
和updateAt
。 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));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.