【问题标题】:How to update value of specific embedded document, inside an array, of a specific document in MongoDB?如何更新 MongoDB 中特定文档的数组内特定嵌入文档的值?
【发布时间】:2011-09-15 04:49:10
【问题描述】:

我的文档中有以下结构:

{
  _id : ObjectId("43jh4j343j4j"), 
  array : [
            { 
              _arrayId : ObjectId("dsd87dsa9d87s9d7"),
              someField : "something",
              someField2 : "something2"
            },
            { 
              _arrayId : ObjectId("sds9a0d9da0d9sa0"),
              someField : "somethingElse",
              someField2 : "somethingElse2"
            }
   ]
 }

我想更新 someFieldsomeField2 但仅针对数组中的一项,即与 _arrayId 匹配的一项(例如 @ 987654323@; 仅适用于本文档(例如 _id : ObjectId("43jh4j343j4j") ),没有其他。

arrayIds 不是文档独有的,这就是为什么我需要它用于特定文档的原因。如果我想为数组中存在的每个文档更新该值,我可以使用$ positional operator,但这不是我想要的。

我正在尝试在 中完成此操作,但命令行解决方案也可以。

【问题讨论】:

    标签: java java mongodb mongodb-java


    【解决方案1】:

    这是 RameshVel 的解决方案翻译成

        DB db = conn.getDB( "yourDB" ); 
        DBCollection coll = db.getCollection( "yourCollection" );
    
        ObjectId _id = new ObjectId("4e71b07ff391f2b283be2f95");
        ObjectId arrayId = new ObjectId("4e639a918dca838d4575979c");
    
        BasicDBObject query = new BasicDBObject();
        query.put("_id", _id);
        query.put("array._arrayId", arrayId);
    
        BasicDBObject data = new BasicDBObject();
        data.put("array.$.someField", "updated");
    
        BasicDBObject command = new BasicDBObject();
        command.put("$set", data);
    
        coll.update(query, command);
    

    【讨论】:

    • 如果我们通过创建 someField 数组来增加一层数组呢?我们可以写一些类似 data.put("array.$.someField.$.anotherField", "updated");不适合我
    • 谢谢,解决了我的问题。 array.$.field 是诀窍(我使用的是 3.5)
    【解决方案2】:

    您仍然可以使用$ positional 运算符来完成此操作。但是您需要指定父文档的 objectid 以及 _arrayid 过滤器。下面的命令行查询工作正常

    db.so.update({_id:ObjectId("4e719eb07f1d878c5cf7333c"),
                  "array._arrayId":ObjectId("dsd87dsa9d87s9d7")},
                  {$set:{"array.$.someField":"updated"}})
    

    【讨论】:

    • 效果很好!谢谢。所以coll.update(query, data) 中的查询就像一个过滤器来查找您正在寻找的文档,并且作为您感兴趣的文档部分的选择器?
    【解决方案3】:

    ...这是使用 mongo-driver 版本 >= 3.1(我的是 3.2.2)的方法:

    final MongoClient mongoClient = new MongoClient(new MongoClientURI(mongoURIString));
    final MongoDatabase blogDatabase = mongoClient.getDatabase("yourDB");
    MongoCollection<Document> postsCollection = blogDatabase.getCollection("yourCollection");
    
    ObjectId _id = new ObjectId("4e71b07ff391f2b283be2f95");
    ObjectId arrayId = new ObjectId("4e639a918dca838d4575979c");
    
    Bson filter = Filters.and(Filters.eq( "_id", id ), Filters.eq("array._arrayId", arrayId));
    Bson setUpdate = Updates.set("array.$.someField", "updated");
    postsCollection.updateOne(postFilter, setUpdate);
    

    【讨论】:

      【解决方案4】:

      由于没有一个答案真正解释了如何做到这一点 a) 在 Java 和 b) 嵌套数组项中的多个字段,这里是 mongo-java-driver 3.12.3 的解决方案。

      import com.mongodb.client.MongoCollection;
      import com.mongodb.client.model.Filters;
      import com.mongodb.client.model.Updates;
      import org.bson.Document;
      import org.bson.types.ObjectId;
      
      MongoClient mongoClient = MongoClients.create(...);
      MongoDatabase db = mongoClient.getDatabase("testDb");
      MongoCollection<Document> collection = db.getCollection("testCollection");
      collection.updateOne(
          Filters.and(
                  Filters.eq("_id", new ObjectId("43jh4j343j4j")),
                  Filters.eq("array._arrayId", new ObjectId("dsd87dsa9d87s9d7"))
          ),
          Updates.combine(
                  Updates.set("array.$.someField", "new value 1"),
                  Updates.set("array.$.someField2", "new value 2")
          )
      );
      

      这个帖子帮助我找到了正确的解决方案,但我必须为完整的解决方案做更多的研究,所以希望其他人也能从我的回答中受益。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-08-02
        • 2014-09-25
        • 2018-05-11
        相关资源
        最近更新 更多