복붙노트

[SPRING] reg 표현식의 배열을 Spring 기반 mongo에 전달 @Query

SPRING

reg 표현식의 배열을 Spring 기반 mongo에 전달 @Query

mongodb와 함께 Spring 부트를 사용하고 있습니다. PagingAndSortingRepository 저장소를 확장하고 다음 함수를 추가했습니다.

@Query("{'title':{ $nin: [?0]}}")
List<Item> findItem(String[] exclude);

/ dog /, / cat /, / horse /와 같은 정규 표현식 배열을 전달하여 제목 중 하나를 가질 수있는 항목을 제외시킬 수 있기를 원합니다.

제외는 문자열로 변환되기 때문에 위의 함수는 작동하지 않습니다. 위의 작업을 수행 할 수 있도록 정규식 배열을 전달하려면 어떻게해야합니까?

해결법

  1. ==============================

    1.컨트롤러 메소드 중 하나에서 Querydsl 술어를 사용하여 문제를 해결할 수 있습니다.

    컨트롤러 메소드 중 하나에서 Querydsl 술어를 사용하여 문제를 해결할 수 있습니다.

    컨트롤러에 다음과 같이 추가하십시오.

    @RequestMapping(value="/search/findByNameRegexNotIn", method = RequestMethod.GET)
    @ResponseBody
    public List<Item> findByNameRegexNotIn(@RequestParam(name = "name") List<String> names) {
        // build a query predicate
        BooleanBuilder predicate = new BooleanBuilder();  // comes from the Querydsl library
        for (String name : names) {
                predicate.and(QItem.item.name.contains(name).not()); // the QItem class is generated by Querydsl
        }
    
        List<Item> items = (List<Item>)repository.findAll(predicate);
    
        return items;
    }
    

    물론 Pageable 매개 변수를 추가하고 List 대신 Page 을 반환 할 수 있습니다.

    편집 :이 유일한 목적으로 Querydsl을 사용하는 경우 다른 솔루션은 쿼리 매개 변수의 기본 바인딩을 무시하는 것입니다.

    public interface ItemRepository extends CrudRepository<Item, String>,
        QueryDslPredicateExecutor<Item>, QuerydslBinderCustomizer<QItem> {
    
        @Override
        default public void customize(QuerydslBindings bindings, QItem item) {
            bindings.bind(item.name).all(
                (path, values) ->  path.matches(StringUtils.collectionToDelimitedString(values, "|")).not());
            // disable query on all parameters but the item name
            bindings.including(item.name);
            bindings.excludeUnlistedProperties(true);
        }
    }
    

    컨트롤러 메소드 :

    @RequestMapping(value="/search/query", method = RequestMethod.GET)
    @ResponseBody
    public List<Item> queryItems(
            @QuerydslPredicate(root = Item.class) Predicate predicate) {
            List<Item> items = (List<Item>)repository.findAll(predicate);
    
            return items;
        }
    

    편집 : 기본 QuerydslBinderCustomizer # customize를 재정의하지 않으려는 경우 자체 바인더를 구현하고 컨트롤러 메서드에서 지정할 수도 있습니다.

    public interface ItemRepository extends CrudRepository<Item, String>,
        QueryDslPredicateExecutor<Item> {
        ...
    }
    

    컨트롤러 메소드 :

    @RequestMapping(value="/search/query", method = RequestMethod.GET)
    @ResponseBody
    public List<Item> queryItems(
            @QuerydslPredicate(root = Item.class, bindings = ItemBinder.class) Predicate predicate) {
            List<Item> items = (List<Item>)repository.findAll(predicate);
    
            return items;
        }
    

    바인더 클래스 :

    class ItemBinder implements QuerydslBinderCustomizer<QItem> {
    
    @Override
    public void customize(QuerydslBindings bindings, QItem item) {
        bindings.bind(item.name).all(
                (path, values) ->  path.matches(StringUtils.collectionToDelimitedString(values, "|")).not()
        );
        bindings.including(item.name);
        bindings.excludeUnlistedProperties(true);
    }
    

    }

    편집 : 소모성과 Querysl에 대해 듣고 싶지 않은 사람들을 위해서. Spring Data Mongodb Reference에서 제안 된 솔루션 사용하기.

    커스텀 리포지터리 (repository) 인터페이스를 정의합니다.

    interface ItemRepositoryCustom {
    
        public Page<Item> findByNameRegexIn(Collection<String> names, Pageable page);
    
    }
    

    사용자 정의 저장소 구현 정의 (Impl 접미사 필요!) :

    public class ItemRepositoryImpl implements ItemRepositoryCustom {
    
        @Autowired
        private MongoOperations operations;
    
        @Override
        public Page<Item> findByNameRegexNotIn(Collection<String> names, Pageable pageable) {
            String pattern = StringUtils.collectionToDelimitedString(names, "|");
            // this time we use org.springframework.data.mongodb.core.query.Query instead of Querydsl predicates
            Query query = Query.query(where("name").regex(pattern).not()).with(pageable);
    
            List<Item> items = operations.find(query, Item.class);
            Page<Item> page = new PageImpl<>(items, pageable, items.size());
    
            return page;
        }
    
    }
    

    이제 ItemRepositoryCustom을 확장하면됩니다.

    public interface ItemRepository extends MongoRepository<Item, String>, ItemRepositoryCustom {
    
    ...
    
    }
    

    그리고 너 끝났어!

  2. from https://stackoverflow.com/questions/36600550/passing-array-of-reg-expressions-to-spring-based-mongo-query by cc-by-sa and MIT license