使用Spring数据mongodb更新嵌入式mongodb文档中的数组字段?
我正在尝试使用SpringDataMongoDB更新mongodb中嵌入文档中的数组字段 我希望在mongodb集合中更新/插入的文档结构如下所示 根据部门的不同类型,可以有更多这样的文档,比如“销售”、“营销”等等使用Spring数据mongodb更新嵌入式mongodb文档中的数组字段?,mongodb,spring-data-mongodb,bson,mongotemplate,Mongodb,Spring Data Mongodb,Bson,Mongotemplate,我正在尝试使用SpringDataMongoDB更新mongodb中嵌入文档中的数组字段 我希望在mongodb集合中更新/插入的文档结构如下所示 根据部门的不同类型,可以有更多这样的文档,比如“销售”、“营销”等等 { "timestamp": "2014-09-26T04:00:00.000Z", "department": "accounts", "employee": [ { "type": "regular",
{
"timestamp": "2014-09-26T04:00:00.000Z",
"department": "accounts",
"employee": [
{
"type": "regular",
"names": [
"Raj",
"Kumar",
"Shankar"
]
},
{
"type": "contract",
"names": [
"Penny",
"Sheldon",
"bob"
]
},
{
"type": "temp",
"names": [
"jerry",
"kramer",
"bubbleboy"
]
}
]
}
基本上,我的更新查询如下所示
db.getCollection('mytest').update(
{
"timestamp" : "2014-09-26T04:00:00.000Z",
"department" : "accounts",
"employee.type" : "regular"
},
{ $addToSet: { "employee.$.names" : "Jo" } },
{
upsert: true
}
)
我添加了upsert:true,因为如果没有与查询匹配的文档,我希望将该文档插入mytest集合
当我从MongoShell执行相同的操作时,我得到以下错误
The positional operator did not find the match needed from the query. Unexpanded update: employee.$.names
即使这样做有效,我也不确定我们是否有类似的支持在SpringDataMongoDB中实现相同的功能
另外,我的另一个查询是,如果我想为多个部门添加/更新员工,比如说“accounts”和“sales”,那么我似乎必须以不同的值执行相同的查询,作为我想相应更新的部门数(如果不存在insert)
是否有更好和高效的选项,例如批量/批处理,在其中,我可以在单个mongo更新查询中同时更新/插入多个部门的员工。另外,spring data mongodb/mongotemplate中是否支持同样的功能。首先,我应该说,由于文档结构具有嵌入式数组,因此需要处理多个场景。如果可能,请尝试重新设计文档结构 对错误的简短回答:- 如果查询未找到匹配的文档,则会出现位置运算符错误 这就是为什么在我下面的解决方案中,我在catch块中处理了这个场景。如果你能通过单元测试,你应该能够理解 解决方案:-
public Boolean updateDepartmentCollectionWithoutFind(String name, String timeStamp)
throws JsonParseException, JsonMappingException, IOException {
MongoOperations mongoOperations = getMongoConnection();
Query query = new Query();
query.addCriteria(Criteria.where("timestamp").is(timeStamp).and("department").is("accounts")
.and("employee.type").is("regular"));
Update update = new Update();
update.addToSet("employee.$.names", name);
try {
System.out.println(query.toString());
System.out.println(update.toString());
WriteResult writeResult = mongoOperations.upsert(query, update, DepartmentCollection.class);
if (writeResult != null) {
System.out.println("111111111111111111 Update with position parameter has been successful :"
+ writeResult.toString());
}
} catch (DataIntegrityViolationException die) {
System.out.println("Update failed ====>" + die.getMessage());
System.out.println("Trying to update without position parameters ...");
Update updateWithoutPositionOperator = new Update();
updateWithoutPositionOperator.addToSet("employee.names", name);
WriteResult writeResultUpsert = mongoOperations.upsert(query, updateWithoutPositionOperator,
DepartmentCollection.class);
if (writeResultUpsert != null) {
System.out.println("2222222222222222222 Update without position parameter has been successful :"
+ writeResultUpsert.toString());
}
}
return true;
}
我的获取连接方法供参考:-
如果您有spring上下文,并且可以根据您的上下文更改上述代码,那么就不需要这样做
@SuppressWarnings("resource")
public MongoOperations getMongoConnection() {
return (MongoOperations) new AnnotationConfigApplicationContext(SpringMongoConfig.class)
.getBean("mongoTemplate");
}
单元测试:-
我发布单元测试是因为您需要了解场景和解决方案。请阅读每个测试和方法名称中的注释,以了解在每个场景中执行哪个upsert
测试3是一种特殊行为。请仔细看看
@Test
public void updateDepartmentCollectionWhenNoDocumentsPresent() throws JsonParseException, JsonMappingException, IOException {
//Second upsert executed (i.e. without positional parameter)
Assert.isTrue(queryOperations.updateDepartmentCollectionWithoutFind("Raj", "2014-09-26T04:00:00.000Z"));
}
@Test
public void updateDCWhenMatchingDocumentsPresentButDocumentHasOnlyRegularEmployeeType() throws JsonParseException, JsonMappingException, IOException {
//Second upsert executed (i.e. without positional parameter)
Assert.isTrue(queryOperations.updateDepartmentCollectionWithoutFind("Jo", "2014-09-26T04:00:00.000Z"));
}
@Test
public void updateDCWhenMultipleTypesPresentButNoRegular() throws JsonParseException, JsonMappingException, IOException {
//First upsert executed (i.e. with positional parameter). However, it creates a new document.
Assert.isTrue(queryOperations.updateDepartmentCollectionWithoutFind("Jo", "2014-09-27T04:00:00.000Z"));
}
@Test
public void updateDCWhenMultipleTypesPresentIncludingRegular() throws JsonParseException, JsonMappingException, IOException {
//First upsert executed (i.e. with positional parameter) and existing document has been updated.
Assert.isTrue(queryOperations.updateDepartmentCollectionWithoutFind("Jo", "2014-09-29T04:00:00.000Z"));
}
您是否有机会查看下面的解决方案,看看它是否解决了您的问题?