从 java 更新 mongodb 中数组中的值
updating a value in an array in mongodb from 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
}
首先我认为我应该首先展开实体数组以获得情绪值,但如果我这样做那么我如何再次缠绕它们并使用与现在相同的格式更新文档但使用新的情绪值 ?
我也找到了这个 link:
MongoDB - Update objects in a document's array (nested updating)
但我无法理解,因为它没有写在 java 查询中,
谁能在 java 中解释我如何做到这一点?
您需要分两步完成:
- 获取所有
_id
个包含具有情感的实体的记录
值 4
.
- 在
find
期间,仅投影具有
匹配查询,以便我们可以处理它以仅使用它的
Sentiment.Value
。为此,请使用位置运算符 ($)。
- 而不是每次都访问数据库来更新每个匹配的
记录,使用BulkAPI,排队更新并执行
终于。
创建批量操作写入器:
BulkWriteOperation bulk = col.initializeUnorderedBulkOperation();
查找在其 Entities.ID
字段中包含值 4
的所有记录。当您将文档与此查询进行匹配时,您将得到整个文档 returned。但是我们不想要整个文档,我们只想要文档的_id,这样我们就可以使用它更新同一个文档,以及文档中值为 4 的 Entity 元素。可能有 n
其他Entity 文件,但它们无关紧要。因此,为了仅获取与查询匹配的实体元素,我们使用位置运算符 $.
DBObject find = new BasicDBObject("Entities.ID",4);
DBObject project = new BasicDBObject("Entities.$",1);
DBCursor cursor = col.find(find, project);
上面的内容 return 例如下面的文档(因为我们的例子假设只有一个输入文档)。如果您注意到,它只包含一个与我们的查询匹配的 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
不允许引用文档字段来检索其值,在单个更新查询中修改它并使用计算值更新它。
我在 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
}
首先我认为我应该首先展开实体数组以获得情绪值,但如果我这样做那么我如何再次缠绕它们并使用与现在相同的格式更新文档但使用新的情绪值 ?
我也找到了这个 link: MongoDB - Update objects in a document's array (nested updating)
但我无法理解,因为它没有写在 java 查询中, 谁能在 java 中解释我如何做到这一点?
您需要分两步完成:
- 获取所有
_id
个包含具有情感的实体的记录 值4
. - 在
find
期间,仅投影具有 匹配查询,以便我们可以处理它以仅使用它的Sentiment.Value
。为此,请使用位置运算符 ($)。 - 而不是每次都访问数据库来更新每个匹配的 记录,使用BulkAPI,排队更新并执行 终于。
创建批量操作写入器:
BulkWriteOperation bulk = col.initializeUnorderedBulkOperation();
查找在其 Entities.ID
字段中包含值 4
的所有记录。当您将文档与此查询进行匹配时,您将得到整个文档 returned。但是我们不想要整个文档,我们只想要文档的_id,这样我们就可以使用它更新同一个文档,以及文档中值为 4 的 Entity 元素。可能有 n
其他Entity 文件,但它们无关紧要。因此,为了仅获取与查询匹配的实体元素,我们使用位置运算符 $.
DBObject find = new BasicDBObject("Entities.ID",4);
DBObject project = new BasicDBObject("Entities.$",1);
DBCursor cursor = col.find(find, project);
上面的内容 return 例如下面的文档(因为我们的例子假设只有一个输入文档)。如果您注意到,它只包含一个与我们的查询匹配的 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
不允许引用文档字段来检索其值,在单个更新查询中修改它并使用计算值更新它。