Spring boot 按条件的动态字段进行常规搜索和筛选(全局搜索)
我有一个场景,需要在Spring中使用mongoTemplate添加条件来执行搜索和筛选 情景: 假设我有Spring boot 按条件的动态字段进行常规搜索和筛选(全局搜索),spring-boot,spring-data,spring-data-mongodb,spring-mongodb,mongotemplate,Spring Boot,Spring Data,Spring Data Mongodb,Spring Mongodb,Mongotemplate,我有一个场景,需要在Spring中使用mongoTemplate添加条件来执行搜索和筛选 情景: 假设我有学生,课程和潜在学生。我只需要定义一些用于搜索和筛选的字段。对于PotentialStudent,它同时包含Student和Course信息,这些信息是在收集所有必需信息并填写给学生和课程之前收集的 搜索字段是用于搜索任一字段的字段。例如:在courseName或courseType中获取匹配的值 过滤器用于过滤特定字段以匹配多个值,并且在FilterParams上设置字段上要过滤的值。也就
学生
,课程
和潜在学生
。我只需要定义一些用于搜索和筛选的字段。对于PotentialStudent
,它同时包含Student
和Course
信息,这些信息是在收集所有必需信息并填写给学生和课程之前收集的
搜索字段是用于搜索任一字段的字段。例如:在courseName
或courseType
中获取匹配的值
过滤器用于过滤特定字段以匹配多个值,并且在FilterParams
上设置字段上要过滤的值。也就是说,如果我在FilterParams.studentType
中得到值,那么对于PotentialStudent
我应该
添加条件以搜索潜在学生的student。键入以查看值列表,而如果为student
添加条件以搜索学生的以键入
public abstract class Model {
@Id
protected String id;
@CreatedDate
protected Date createdDateTime;
@LastModifiedDate
protected Date modifiedDateTime;
protected abstract List<String> searchFields();
protected abstract Map<String, String> filterFields();
}
@Getter
@Setter
@Document("student")
public class Student extends Model {
private String firstName;
private String lastName;
private String address;
private StudentType type;
@Override
protected List<String> searchFields() {
return Lists.newArrayList("firstName","lastName","address");
}
@Override
protected Map<String, String> filterFields() {
Map<String, String> filterMap = Maps.newHashMap();
filterMap.put("studentType", "type");
return filterMap;
}
}
@Getter
@Setter
@Document("course")
public class Course extends Model {
private String courseName;
private String courseType;
private int duration;
private Difficulty difficulty;
@Override
protected List<String> searchFields() {
return Lists.newArrayList("courseName","courseType");
}
@Override
protected Map<String, String> filterFields() {
Map<String, String> filterMap = Maps.newHashMap();
filterMap.put("courseDifficulty", "difficulty");
return filterMap;
}
}
@Getter
@Setter
@Document("course")
public class PotentialStudent extends Model {
private Student student;
private Course course;
@Override
protected List<String> searchFields() {
return Lists.newArrayList("student.firstName","student.lastName","course.courseName");
}
@Override
protected Map<String, String> filterFields() {
Map<String, String> filterMap = Maps.newHashMap();
filterMap.put("studentType", "student.type");
filterMap.put("courseDifficulty", "course.difficulty");
return filterMap;
}
}
}
public class FilterParams {
private List<StudentType> studentTypes;
private List<Difficulty> difficulties;
}
public class PageData<T extends Model> {
public void setPageRecords(List<T> pageRecords) {
this.pageRecords = pageRecords;
}
private List<T> pageRecords;
}
//Generic Search Filter Implementation Class
public class GenericSearchFilter {
public <T extends Model> PageData getRecordsWithPageSearchFilter(Integer page, Integer size, String sortName, String sortOrder, String value, FilterParams filterParams, Class<T> ormClass) {
PageRequestBuilder pageRequestBuilder = new PageRequestBuilder();
Pageable pageable = pageRequestBuilder.getPageRequest(page, size, sortName, sortOrder);
Query mongoQuery = new Query().with(pageable);
//add Criteria for the domain specified search fields
Criteria searchCriteria = searchCriteria(value, ormClass);
if (searchCriteria != null) {
mongoQuery.addCriteria(searchCriteria);
}
//Handle Filter
query.addCriteria(Criteria.where(filterFields().get("studentType")).in(filterParams.getStudentTypes()));
query.addCriteria(Criteria.where(filterFields().get("courseDifficulty")).in(filterParams.getDifficulty()));
List<T> records = mongoTemplate.find(mongoQuery, ormClass);
PageData pageData = new PageData();
pageData.setPageRecords(records);
return pageData;
}
private <T extends BaseDocument> Criteria searchCriteria(String value, Class<T> ormClass) {
try {
Criteria orCriteria = new Criteria();
if (StringUtils.isNotBlank(value)) {
BaseDocument document = ormClass.getDeclaredConstructor().newInstance();
Method method = ormClass.getDeclaredMethod("searchFields");
List<String> records = (List<String>) method.invoke(document, null);
Criteria[] orCriteriaArray = records.stream().map(s -> Criteria.where(s).regex(value, "i")).toArray(Criteria[]::new);
orCriteria.orOperator(orCriteriaArray);
}
return orCriteria;
} catch (Exception e) {
log.error(e.getMessage());
}
return null;
}
}
公共抽象类模型{
@身份证
受保护的字符串id;
@创建数据
受保护日期createdDateTime;
@最后修改日期
保护日期修改日期时间;
受保护的抽象列表搜索字段();
受保护的抽象映射筛选器字段();
}
@吸气剂
@塞特
@文件(“学生”)
公共班级学生扩展模式{
私有字符串名;
私有字符串lastName;
私有字符串地址;
私立学生型;
@凌驾
受保护的列表搜索字段(){
返回列表。newArrayList(“firstName”、“lastName”、“address”);
}
@凌驾
受保护的映射筛选器字段(){
Map filterMap=Maps.newHashMap();
filterMap.put(“studentType”、“type”);
返回过滤器映射;
}
}
@吸气剂
@塞特
@文件(“课程”)
公共课扩展模式{
私有字符串courseName;
私有字符串类型;
私有整数持续时间;
私人困难;
@凌驾
受保护的列表搜索字段(){
返回列表。newArrayList(“courseName”、“courseType”);
}
@凌驾
受保护的映射筛选器字段(){
Map filterMap=Maps.newHashMap();
filterMap.put(“课程难度”、“难度”);
返回过滤器映射;
}
}
@吸气剂
@塞特
@文件(“课程”)
公共课潜在学生扩展模型{
私立学生;
私人课程;
@凌驾
受保护的列表搜索字段(){
返回列表.newArrayList(“student.firstName”、“student.lastName”、“course.courseName”);
}
@凌驾
受保护的映射筛选器字段(){
Map filterMap=Maps.newHashMap();
filterMap.put(“studentType”、“student.type”);
filterMap.put(“课程难度”、“课程难度”);
返回过滤器映射;
}
}
}
公共类筛选器参数{
私人名单学生类型;
私人名单困难;
}
公共类页面数据{
公共作废setPageRecords(列表pageRecords){
this.pageRecords=页面记录;
}
私人名单记录;
}
//通用搜索筛选器实现类
公共类GenericSearchFilter{
公共页面数据getRecordsWithPageSearchFilter(整型页面、整型大小、字符串排序名、字符串排序器、字符串值、FilterParams FilterParams、类或类){
PageRequestBuilder PageRequestBuilder=新的PageRequestBuilder();
Pageable Pageable=pageRequestBuilder.getPageRequest(页面、大小、排序名、排序器);
Query mongoQuery=new Query().with(可分页);
//为域指定的搜索字段添加条件
Criteria searchCriteria=searchCriteria(值或类别);
if(searchCriteria!=null){
mongoQuery.addCriteria(searchCriteria);
}
//手柄过滤器
query.addCriteria(Criteria.where(filterFields().get(“studentType”)).in(filterParams.getStudentTypes());
query.addCriteria(Criteria.where(filterFields().get(“CourseDifficity”)).in(filterParams.getDefficity());
List records=mongoTemplate.find(mongoQuery、ormClass);
PageData PageData=新的PageData();
pageData.setPageRecords(记录);
返回页面数据;
}
私有条件searchCriteria(字符串值、类或类){
试一试{
标准或标准=新标准();
if(StringUtils.isNotBlank(值)){
BaseDocument document=ormClass.getDeclaredConstructor().newInstance();
方法Method=ormClass.getDeclaredMethod(“搜索字段”);
List records=(List)方法.invoke(document,null);
Criteria[]或CriteriaArray=records.stream().map(s->Criteria.where(s).regex(值,“i”)).toArray(Criteria[]::new);
orCriteria.orOperator(orCriteriaArray);
}
回归标准;
}捕获(例外e){
log.error(例如getMessage());
}
返回null;
}
}
在这种情况下,我的问题是如何以更好的动态方式处理过滤器案例,以及如果需要在所有文档类型中搜索每个类型上的指定字段,如何实现全局搜索。您要查找的是“文本索引”吗?您使用@TextIndexed from spring data mongodb注释每个字段,并使用以下查询进行搜索:{$text:{$search:?1}}@Eduard不完全,我需要在任何定义的字段上搜索匹配的任何单词或字母,并且我正在使用正则表达式的条件来获取要搜索的所需字段,并将搜索框中插入的值与定义字段上的任何匹配项相匹配。@Eduard。您知道如何在SpringDataMongoDB上实现视图,以便能够跨mu定义搜索吗