【问题标题】:Mongo Java Driver - How to update a subdocument into an array elementMongo Java 驱动程序 - 如何将子文档更新为数组元素
【发布时间】:2016-06-17 13:39:48
【问题描述】:

如何更新数组元素子文档中的特定字段?

我的问题类似于下面的问题,但在我的情况下,我只需要更新一个子文档值。

MongoDB: How do I update a single subelement in an array, referenced by the index within the array?

我有以下文档模型:

{
  _id : "xpto",
  other_stuff ... ,
  templates : [
    { 
        templateId:"template-a" 
        body: {
            en_US:"<p>Hello World!</p>"
        }
    },
    { 
        templateId:"template-b" 
        body: {
            es_ES:"<p>Holla !</p>"
        }
    }
  ]
}

所以,在 mongodb shell 中,以下语句非常适合我:

db.apiClient.update({"_id":"xpto","templates.templateId":"template-b"}, {$set:{"templates.$.body.es_ES":"<h1>Gracias !</h1>"}})

但是,当我尝试使用 Mongo Java Driver 执行此操作时,我得到了 IllegalArgumentException。

    BasicDBObject selectQuery = new BasicDBObject("_id", "xpto");
    selectQuery.put("templates.templateId", "template-b");

    BasicDBObject updateQuery = new BasicDBObject();
    for(String locale : template.getBody().keySet()) {

        String updateBodyLocaleExpression = new StringBuilder()
                .append("templates.$.body.").append(locale).toString();

        String updateBodyLocaleValue = template.getBody().get(locale);

        updateQuery.put(updateBodyLocaleExpression, updateBodyLocaleValue);

    }

    updateQuery.put("$set", updateQuery);
    getCollection(COLLECTION_NAME).update(selectQuery, updateQuery, true, true);

它抛出以下异常:

Caused by: java.lang.IllegalArgumentException: Invalid BSON field name templates.$.body.es_ES
        at org.bson.AbstractBsonWriter.writeName(AbstractBsonWriter.java:494)
        at com.mongodb.DBObjectCodec.encode(DBObjectCodec.java:127)
        at com.mongodb.DBObjectCodec.encode(DBObjectCodec.java:61)
        at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:63)
        at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:29)
        at com.mongodb.connection.RequestMessage.addDocument(RequestMessage.java:253)
        at com.mongodb.connection.RequestMessage.addCollectibleDocument(RequestMessage.java:219)
        at com.mongodb.connection.UpdateMessage.encodeMessageBodyWithMetadata(UpdateMessage.java:77)
        at com.mongodb.connection.RequestMessage.encodeWithMetadata(RequestMessage.java:160)
        at com.mongodb.connection.WriteProtocol.execute(WriteProtocol.java:85)

我的代码有问题吗?

谢谢。

【问题讨论】:

    标签: java mongodb mongo-java-driver


    【解决方案1】:

    是的。你构造了错误的updateQuery。您将字段 templates.$.body... 放入 BasicDbObject 中,然后将相同的文档添加到 $set 字段中。 MongoDB 尝试更新 field templates.$.body.,这里 $ 是字段名称的一部分,而不是运算符。

    这是工作示例:

        //List is for testing purposes only
        List<String> locales = Arrays.asList("en_US", "en_UK");
    
        Document query = new Document("_id", "xpto")
                .append("templates.templateId", "template-b");
    
        Document updateQuery = new Document();
        for (String locale : locales) {
            updateQuery.put("templates.$.body." + locale, "<pre>Updated " + locale + "</pre>");
        }
        collection.updateOne(query, new Document("$set", updateQuery));
    

    Document 与 BasicDbObject 几乎相同,但更通用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-04
      • 1970-01-01
      • 1970-01-01
      • 2016-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-15
      相关资源
      最近更新 更多