Sie können es ausarbeiten, indem Sie ein Querydsl Prädikat in einer Ihrer Controller-Methode verwenden.
so etwas zu Ihrem Controller hinzufügen:
@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;
}
Sie können einen Pageable Parameter natürlich hinzufügen und eine Seite <Artikel> statt einer Liste zurück.
Edit: Eine andere Lösung, wenn Sie Querydsl für diesen einzigen Zweck verwenden, besteht darin, die Standardbindungen Ihres Abfrageparameters zu überschreiben.
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);
}
}
Die Controller-Methode:
@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;
}
Edit: Wenn Sie nicht die Standard QuerydslBinderCustomizer # customize Sie wan't außer Kraft zu setzen, können Sie auch Ihr eigenes Bindemittel implementieren und in die angeben Controller-Methode.
public interface ItemRepository extends CrudRepository<Item, String>,
QueryDslPredicateExecutor<Item> {
...
}
Die Controller-Methode:
@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;
}
Die Bindemittelklasse:
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);
}
}
Edit: im Interesse über die Vollständigkeit und diejenigen, die nicht wollen, über Querysl zu hören. Verwenden der in Spring Data Mongodb Reference vorgeschlagenen Lösung.
eine Schnittstelle benutzerdefinierte Repository definieren:
interface ItemRepositoryCustom {
public Page<Item> findByNameRegexIn(Collection<String> names, Pageable page);
}
eine benutzerdefinierte Repository Implementierung definieren (Impl postfix erforderlich!):
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;
}
}
Jetzt ItemRepositoryCustom einfach erweitern:
public interface ItemRepository extends MongoRepository<Item, String>, ItemRepositoryCustom {
...
}
Und du bist fertig!
Es scheint so, als ob Sie den * Fall * gefunden haben, der nicht direkt mit "Standard" -Abfrage-Methoden oder mit der @Query-Annotation (ab heute) gelöst werden kann. Möchten Sie Ihre Repository-Instanz in einem Controller verwenden? Wenn ja, kann ich eine Idee haben. –
Ja Ich verwende den Repo in einer @RestController-Instanz. Ich dachte daran, das Array in einen einzigen Regex umzuwandeln und $ regex stattdessen zu verwenden, aber es ist keine sehr saubere Lösung. – jvence
Ihre einzige Regex würde wahrscheinlich Pipes enthalten und ich bin mir ziemlich sicher, dass Spring gut auf Pipes in URLs reagiert. –