Skip to content

DATAMONGO-2215 - Add support for array filters to Update. #656

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from

Conversation

christophstrobl
Copy link
Member

We now support filtered positional $[<identifier>] operator via Updates. This allows to specify a filter criteria chain for the elements in an array.

new Update()
    .set("grades.$[element]", 100)
    .filterArray(Criteria.where("element").gte(100));

Depends on: #653 (DATAMONGO-2054)

We now support the $[] array update operator when mapping Update.
We now support filtered positional $[<identifier>] operator via Updates. This allows to specify a filter criteria chain for the elements in an array.

new Update()
    .set("grades.$[element]", 100)
    .filterArray(Criteria.where("element").gte(100));

Array filters can be used for MongoOperations#update* & MongoOperations#findAndMofify
mp911de pushed a commit that referenced this pull request Mar 5, 2019
We now support filtered positional $[<identifier>] operator via Updates. This allows to specify a filter criteria chain for the elements in an array.

new Update()
    .set("grades.$[element]", 100)
    .filterArray(Criteria.where("element").gte(100));

Array filters can be used for MongoOperations#update* & MongoOperations#findAndModify

Original pull request: #656.
mp911de added a commit that referenced this pull request Mar 5, 2019
Update Javadoc to reflect that array filters are used in their raw form without domain-type related type- or field mapping.

Original pull request: #656.
@mp911de
Copy link
Member

mp911de commented Mar 5, 2019

That's merged and polished now.

@mp911de mp911de closed this Mar 5, 2019
@mp911de mp911de deleted the issue/DATAMONGO-2215 branch March 5, 2019 09:52
@SaravananParamasivan
Copy link

not able to use arrayFilters with update

@SaravananParamasivan
Copy link

getting error like add cast to receiver

@aleboulanger
Copy link

@mp911de
Any possibility to have a report to Spring Data 1.x ?

@mp911de
Copy link
Member

mp911de commented Jul 4, 2019

We do not backport features, also the change is not compatible because 1.x uses the DBObject API. 1.x goes end of life in August. Please upgrade to the 2.x line.

@aleboulanger
Copy link

thank you @mp911de.
is it possible, in the mean time, to make a native query with the @query annotation for example on the spring data repository method ?

@mp911de
Copy link
Member

mp911de commented Jul 5, 2019

No. Native queries (command documents) are assembled by the driver depending on the functionality that should be used. We're using a higher-level API to invoke e.g. find operations instead of using the execute functionality.

@vruddhishah
Copy link

How can I use this dependency with spring boot 2.1.4.Release, As soon as I add this jar via maven shaded plugin, It shows me other errors where it is not able to fetch something from org.springframework.data.*

@Panksnazi
Copy link

Can we use two identifiers with this change. If yes how to write equivalent spring-data-mongodb query for the below query:
db.animals.update(
{"animalID":"1234"},
{ $set:{"species.$[element].subspecies.$[subspecies].spieceName","German Shepard"}},
{ arrayFilters : [{"element.speciesID":"1"},{"subspecies.subspeciesID":"1"} ] }
)

@vruddhishah
Copy link

@Panksnazi
Copy link

Panksnazi commented Aug 5, 2019

@vruddhishah I am using spring-boot 2.2.0.M4 , I am looking into using identifier which I believe was added as mentioned by christophstrobl. For more details, please refer the below link

https://stackoverflow.com/questions/57345850/adding-multiple-identifier-in-filterarray-to-update-a-field-in-nested-subdocu

@vruddhishah
Copy link

Can we use two identifiers with this change. If yes how to write equivalent spring-data-mongodb query for the below query:
db.animals.update(
{"animalID":"1234"},
{ $set:{"species.$[element].subspecies.$[subspecies].spieceName","German Shepard"}},
{ arrayFilters : [{"element.speciesID":"1"},{"subspecies.subspeciesID":"1"} ] }
)

As per your question, it seemed like you are searching for equivalent spring-data-mongodb query. Hence the relevant reference link was provided. But after the additional information provided, I understand your question now!! Thanks

@caryfang
Copy link

spring-data-mongodb 2.2.1版本以下的,可以使用BasicBSONObject里的基础方法来支持filterArray方法:

`/**

  • User: fangchao
  • Date: 2023/1/12
  • Time: 14:40
    */
    @Getter
    @AllArgsConstructor
    public enum MongoUpdateOperator {
    INC("$inc"),
    SET("$set");

String code;
}

/**

  • User: fangchao
  • Date: 2023/1/12
  • Time: 20:45
    */
    @component
    public class MongoToolUtils {

/**

  • 更新mongo表内嵌数组指定元素
  • spring-data-mongodb 2.2.1版本才支持的写法:
  • mongoTemplate.updateMulti(
  • Query.query(criteria),
  • Update.update(
  • updateKey_prefix + "$[elem].shop.shopName",
  • sampleShopDTO.getShopName())
  • .filterArray(Criteria.where("elem.shop.shopId").is(sampleShopDTO.getShopId())),
  • entityClass);
  • 为了弥补spring-data-mongodb低版本没有Update().filterArray方法
  • 这里采用原生mongo语法来执行:
  • @param mongoTemplate
  • @param tabName 更新的文档表名
  • @param query 更新的文档查询条件
  • @param arrayName 更新的内嵌数组名
  • @param updateMap 对内嵌数组元素不同操作的更新map
  • @param eleFilter 更新内嵌数组元素的过滤条件
  • @return
    */
    public static UpdateResult updateMongoArrayElement(
    MongoTemplate mongoTemplate,
    String tabName,
    Criteria query,
    String arrayName,
    Map<MongoUpdateOperator, JSONObject> updateMap,
    Criteria eleFilter){
    BasicDBObject update = new BasicDBObject();
    UpdateOptions updateOptions = new UpdateOptions();
// 设置$set和$inc等操作符对应的元素更新
for (MongoUpdateOperator operator : updateMap.keySet()){
  BasicBSONObject eleSetBson = new BasicBSONObject();
  JSONObject eleSetJson = updateMap.get(operator);
  for (String key : eleSetJson.keySet()){
    eleSetBson.put(arrayName.concat(".$[item].").concat(key), eleSetJson.get(key));
  }
  update.put(operator.getCode(), eleSetBson);
}

// 组装arrayFilters过滤内容
BasicDBObject eleFilterBson = new BasicDBObject();
Document filter = eleFilter.getCriteriaObject();
for (String key : filter.keySet()){
  eleFilterBson.put("item.".concat(key), filter.get(key));
}
updateOptions.arrayFilters(Lists.newArrayList(eleFilterBson));
return mongoTemplate.getCollection(tabName).updateMany(
    query.getCriteriaObject(),
    update,
    updateOptions
);

}

/**

BeanMap beanMap = BeanMap.create(pojo);
for (Object object : beanMap.entrySet()) {
  if (object instanceof Map.Entry) {
    Map.Entry<String , Object> entry = (Map.Entry<String, Object>)object ;
    String key = entry.getKey();
    doc.put(key, beanMap.get(key));
  }
}

return doc;

}
}`

@christophstrobl
Copy link
Member Author

@caryfang if there's an issue related to this ticket please care to open a new one and please do spend some time describing it. Ideally take the time to provide a complete minimal sample (something that we can unzip or git clone, build, and deploy) that reproduces the problem.
Given the mentioned version (2.2.1) is out of support since Sept. 2020 you may also try upgrading to a more recent one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants