我正在使用mongodb的Spring启动。我扩展了PagingAndSortingRepository存储库并添加了以下函数
@Query("{'title':{ $nin: [?0]}}")
List<Item> findItem(String[] exclude);
我希望能够传递一系列正则表达式,例如/ dog /,/ cat /,/ horse /,以排除任何可能在其标题中包含其中一个的项目。
上述功能不起作用,因为排除转换为字符串。如何传递正则表达式数组才能执行上述操作?
答案 0 :(得分:2)
您可以在其中一种控制器方法中使用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参数并返回Page&lt; Item&gt;而不是列表。
编辑:如果您为此唯一目的使用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中提出的解决方案。
定义自定义存储库界面:
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 {
...
}
你已经完成了!