0

配列要素のサブドキュメントの特定のフィールドを更新するにはどうすればよいですか?

私の質問は以下のようなものですが、私の場合はサブドキュメントの値だけを更新する必要があります。

MongoDB:配列内のインデックスによって参照される、配列内の単一のサブ要素を更新するにはどうすればよいですか?

私は次のドキュメンテーションモデルを持っています:

{
  _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 シェルでは、次のステートメントは私にとって完璧に機能します。

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)

私のコードに何か問題がありますか?

ありがとう。

4

1 に答える 1

1

はい。あなたは間違って構築しますupdateQuery。フィールドtemplates.$.body...を BasicDbObject に配置してから、同じドキュメントを$setフィールドに追加します。MongoDB はフィールド 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 とほぼ同じですが、より一般的です。

于 2016-06-17T14:33:57.717 に答える