当前位置: 首页 > 知识库问答 >
问题:

将reg表达式数组传递给基于spring的mongo@Query

仲孙经赋
2023-03-14

我在mongoDB中使用Spring Boot。我扩展了PagingAndSortinRepository存储库并添加了以下功能

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

我希望能够向它传递一个正则表达式数组,例如/dog/、/cat/、/horse/,以排除标题中可能包含其中一个正则表达式的任何项目。

上述函数不起作用,因为排除已转换为字符串。如何传递正则表达式数组来执行上述操作?

共有2个答案

秦信瑞
2023-03-14

您可以传递java。util。正则表达式。方法的模式[]。这将在引擎盖下转换为regex数组:

@Query("{'title':{ $nin: ?0}}")
List<Item> findItem(Pattern[] exclude);
秦凯定
2023-03-14

您可以通过在一个控制器方法中使用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;
}

当然,您可以添加一个可分页参数并返回一个页面


编辑:如果仅出于此目的使用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#自定义,您还可以实现自己的绑定器并在控制器方法中指定它。

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参考中提出的解决方案

定义自定义存储库接口:

interface ItemRepositoryCustom {

    public Page<Item> findByNameRegexIn(Collection<String> names, Pageable page);

}

定义自定义存储库实现(需要Impl postfix!):

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 {

...

}

你完了!

 类似资料:
  • 这是正确的行为吗?如果是这样,有没有办法接受带有的C样式数组?

  • 问题内容: 我有这样的查找声明 它给出了答案。但是我需要某个变量值,而不是那个杂乱的值MT。如何实现呢?谢谢。 更新 我试过像“ /。 ” + searchterm +“ ./ ”无效。 问题答案: 除了使用内联语法创建正则表达式外,还可以使用RegExp对象基于字符串创建一个正则表达式

  • 我有一个类型为的自定义组件,它通过以下行添加到路由中: 创建一个终结点和消费者(类型为),该终结点和消费者反过来会发出消息,这些消息将到达和管道的其余部分。 为了进行监控,我需要消费者调用一个非驼峰对象上的方法,我正在创建一个Springbean。Camel管道对性能非常敏感,因此我无法将分成两半,并将监视器调用作为Camel组件插入它们之间(我的首选解决方案,因为不必真正了解监视器)。我不愿意将

  • 问题内容: 我在烧瓶中有一个称为数组的函数,该函数接收一个列表并打印出列表中的项目: 在客户端,我想将名为str的javascript数组传递给该数组。我该怎么办?这就是我现在所拥有的,但是Flask没有读取添加的变量。有任何想法吗? 问题答案: Flask具有一个称为request的内置对象。在请求中有一个称为args的multidict。 您可以用来检索查询字符串的值。 当然,这需要一个get

  • 要将数组参数传递给函数,需指定不带方括号的数组名。例如,如果数组hourlyTemperatures声明如下: int hourlyTemperatures[24]; 则下列函数调用语句: modifyArray(hourlyTemperatutes,24); 将数组 hourlyTemperatures 及其长度传递给函数 modifyArray。将数组传递给函数时,通常也将其长度传递给函数,使

  • 我有一组带有时间戳的日志,需要按一些不存在的“虚拟会话”对这些日志进行分组。 如果上一个会话的最后一次登录和第一次登录之间有半个小时,则新的分组会话开始。 例如,我们有以下一组数据: 它应该分组在两个虚拟会话中。作为分组的结果,我可以在mongo aggregate$group中获得每个组的最小和最大时间,但是如何编写正确的表达式呢? 预期的答案大概是