【问题标题】:updating a value in an array in mongodb from java从java更新mongodb数组中的值
【发布时间】:2015-01-08 02:22:01
【问题描述】:

我在 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
    }

首先,我认为我应该首先展开 Entities 数组以获得情绪值,但如果我这样做了,那么我该如何再次展开它们并使用与现在相同的格式但使用新的情绪值更新文档?

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

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

【问题讨论】:

  • 不,因为这不是一个简单的更新,我需要获取该 entityid 的当前情绪值并将其添加例如 4 并除以 2
  • 我认为您问题中描述的文档与您实际建议的结构不同。没有像sentiment.value这样的字段,执行上述操作我们得到的值是12。你能检查一下文档结构是否正确吗?
  • @BatScream 对不起,你是对的,我更新了文档

标签: mongodb-query mongodb-java


【解决方案1】:

您需要分两步完成:

  • 获取所有包含情感实体的记录_id4
  • find期间,仅投影具有 匹配查询,以便我们可以处理它以仅使用它的 Sentiment.Value。为此,请使用位置运算符 ($)。
  • 而不是每次都访问数据库来更新每个匹配的 记录,使用Bulk API,将更新排队并执行 最后。

创建批量操作写入器:

    BulkWriteOperation bulk = col.initializeUnorderedBulkOperation();

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

    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 不允许引用文档字段来检索其值、修改它并使用计算值更新它, 在单个更新查询中。

【讨论】:

  • 非常感谢,是的,它起作用了,只是一个简单的问题:你能解释一下 DBObject project = new BasicDBObject("Entities.$",1);更多的?例如其中的 1 是什么?
  • @HamedMinaee - 请查看我的更新答案。要了解有关位置运算符的更多信息,请单击我的答案中的$ 符号。(有两个,都通过)
  • 现在我明白了,但为什么 1 为什么不是 2 ?我仍然不知道那个 1 指向什么?
  • 投影的允许值为010 将排除该字段,1 将包括该字段。它不是索引。
  • 太棒了,非常有帮助的答案:)
猜你喜欢
  • 2011-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-18
  • 2015-08-27
  • 1970-01-01
  • 2016-02-09
  • 2018-03-14
相关资源
最近更新 更多