Spring boot 按条件的动态字段进行常规搜索和筛选(全局搜索)

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上设置字段上要过滤的值。也就

我有一个场景,需要在Spring中使用mongoTemplate添加条件来执行搜索和筛选

情景:

假设我有
学生
课程
潜在学生
。我只需要定义一些用于搜索和筛选的字段。对于
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定义搜索吗