从Java更新mongodb中数组中的值 [英] updating a value in an array in mongodb from java

查看:1046
本文介绍了从Java更新mongodb中数组中的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在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-更新文档数组中的对象(嵌套更新)

但是我不明白,因为它不是用Java查询编写的, 谁能解释一下我如何在Java中做到这一点?

解决方案

您需要分两个步骤进行操作:

  • 获取所有包含具有情感实体的记录的_id4.
  • find中,仅投影具有以下内容的实体子文档 匹配查询,以便我们可以处理它以仅使用其查询 Sentiment.Value.为此,请使用位置运算符( $ ).
  • 与其每次都访问数据库来更新每个匹配项 记录,请使用批量 API将更新排入队列并执行它 终于.

创建批量操作编写器:

    BulkWriteOperation bulk = col.initializeUnorderedBulkOperation();

在其Entities.ID字段中查找所有包含值4的记录.将文档与此查询匹配时,您将获得整个文档.但是我们不想要整个文档,我们只希望使用文档的_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不允许引用文档字段来检索其值,对其进行修改并使用计算值对其进行更新,在一个更新查询中.

I have couple of documens in mongodb as follow:

{
"_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
        }
    }
]

}

Now I want to update the document that has Entities.ID=4 by adding (Sentiment.Value+4)/2 for example in the above example after update we have 12.

I wrote the following code but I am stuck in the if statement as you can see:

 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
    }

First I thought I should unwind the Entities array first to get the value of sentiment but if I do that then how can I wind them again and update the document with the same format as it has now but with the new sentiment value ?

also I found the this link as well : MongoDB - Update objects in a document's array (nested updating)

but I could not understand it since it is not written in java query, can anyone explain how I can do this in java?

解决方案

You need to do this in two steps:

  • Get all the _id of the records which contain a Entity with sentiment value 4.
  • During the find, project only the entity sub document that has matched the query, so that we can process it to consume only its Sentiment.Value. Use the positional operator($) for this purpose.
  • Instead of hitting the database every time to update each matched record, use the Bulk API, to queue up the updates and execute it finally.

Create the Bulk operation Writer:

    BulkWriteOperation bulk = col.initializeUnorderedBulkOperation();

Find all the records which contain the value 4 in its Entities.ID field. When you match documents against this query, you would get the whole document returned. But we do not want the whole document, we would like to have only the document's _id, so that we can update the same document using it, and the Entity element in the document that has its value as 4. There may be n other Entity documents, but they do not matter. So to get only the Entity element that matches the query we use the positional operator $.

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

What the above could would return is the below document for example(since our example assumes only a single input document). If you notice, it contains only one Entity element that has matched our query.

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

Iterate each record to queue up for update:

    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);
    }

Finally Update:

    bulk.execute();

You need to do a find() and update() and not simply an update, because currently mongodb does not allow to reference a document field to retrieve its value, modify it and update it with a computed value, in a single update query.

这篇关于从Java更新mongodb中数组中的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆