从java中更新mongodb中数组中的值

时间:2015-01-08 02:22:02

标签: mongodb-query mongodb-java

我在mongodb中有几个文件如下:

{
"_id" : ObjectId("54901212f315dce7077204af"),
"Date" : ISODate("2014-10-20T04:00:00.000Z"),
"Type" : "Twitter",
"Entities" : [ 
    {
        "ID" : 4,
        "Name" : "test1",
        "Sentiment" : {
            "Value" : 20,
            "Neutral" : 1
        }
    },
    {
        "ID" : 5,
        "Name" : "test5",
        "Sentiment" : {
            "Value" : 10,
            "Neutral" : 1
        }
    }
]

}

现在我想通过添加(Sentiment.Value + 4)/ 2来更新具有Entities.ID = 4的文档,例如在上面的示例中我们有12个。

我编写了以下代码,但我仍然坚持使用if语句:

 DBCollection collectionG;
   collectionG = db.getCollection("GraphDataCollection");
    int entityID = 4;
    String entityName = "test";
    BasicDBObject queryingObject = new BasicDBObject();
    queryingObject.put("Entities.ID", entityID);
    DBCursor cursor = collectionG.find(queryingObject);

    if (cursor.hasNext())
    {
        BasicDBObject existingDocument = new BasicDBObject("Entities.ID", entityID);
        //not sure how to update the sentiment.value for entityid=4
    }

首先我认为我应该首先解开实体数组以获得情绪的价值,但如果我这样做,那么我怎样才能再次将它们卷起来并使用与现在相同的格式更新文档但是使用新的情绪值?

我也找到了这个链接: MongoDB - Update objects in a document's array (nested updating)

但我无法理解,因为它不是用java查询编写的, 任何人都可以解释我如何在java中做到这一点?

1 个答案:

答案 0 :(得分:2)

您需要分两步完成此操作:

  • 获取包含具有情绪的实体的所有_id条记录 价值4
  • find期间,仅投影具有的实体子文档 匹配查询,以便我们可以处理它只消耗它 Sentiment.Value。为此,请使用位置运算符($)。
  • 而不是每次更新每个匹配的数据库 记录,使用Bulk API来排队更新并执行它 最后。

创建批量操作编写器:

    BulkWriteOperation bulk = col.initializeUnorderedBulkOperation();

4字段中查找包含值Entities.ID的所有记录。将文档与此查询匹配时,将返回整个文档。但是我们不想要整个文档,我们希望只有文档的_id,这样我们就可以使用它来更新同一个文档,并且文档中的Entity元素的值为4。是n其他实体文件,但它们并不重要。因此,为了只获得与查询匹配的Entity元素,我们使用位置运算符$

    DBObject find = new BasicDBObject("Entities.ID",4);
    DBObject project = new BasicDBObject("Entities.$",1);
    DBCursor cursor = col.find(find, project);

以上内容可能会返回以下文档(例如,因为我们的示例仅假设一个输入文档)。如果您注意到,它只包含一个与我们的查询匹配的Entity元素。

{
        "_id" : ObjectId("54901212f315dce7077204af"),
        "Entities" : [
                {
                        "ID" : 4,
                        "Name" : "test1",
                        "Sentiment" : {
                                "Value" : 12,
                                "Neutral" : 1
                        }
                }
        ]
}

迭代每个记录以排队等待更新:

    while(cursor.hasNext()){
        BasicDBObject doc = (BasicDBObject)cursor.next();
        int curVal = ((BasicDBObject)
                     ((BasicDBObject)((BasicDBList)doc.get("Entities")).
                     get(0)).get("Sentiment")).getInt("Value");
        int updatedValue = (curVal+4)/2;
        DBObject query = new BasicDBObject("_id",doc.get("_id"))
                         .append("Entities.ID",4);
        DBObject update = new BasicDBObject("$set",
                          new BasicDBObject("Entities.$.Sentiment.Value",
                                             updatedValue));
        bulk.find(query).update(update);
    }

最后更新:

    bulk.execute();

您需要执行find()update(),而不仅仅是update,因为目前mongodb不允许引用文档字段来检索其值,请修改它,并在单个更新查询中使用计算值更新它。