Java 如何使用MongoTemplate的类属性过滤数据?

Java 如何使用MongoTemplate的类属性过滤数据?,java,spring-boot,mongotemplate,Java,Spring Boot,Mongotemplate,我第一次使用MongoTemplate。 使用Postman,我点击API并将JSON作为@RequestBody传递,以获得经过筛选的学生列表 模型类 Student.java Name.java 控制器 StudentController.java …而且它工作得很好。 当我试图使用“firstName”或“lastName”属性过滤数据时,问题就开始了 这是我试图发送的内容: { "name": { "firstName": "Shamin" } } 我从

我第一次使用MongoTemplate。 使用Postman,我点击API并将JSON作为@RequestBody传递,以获得经过筛选的学生列表

模型类

Student.java

Name.java

控制器

StudentController.java

…而且它工作得很好。 当我试图使用“firstName”或“lastName”属性过滤数据时,问题就开始了

这是我试图发送的内容:

{
    "name": {
        "firstName": "Shamin"
    }
}
我从邮递员那里得到的回报是:

{
    "timestamp": "2018-08-09T12:01:58.620+0000",
    "status": 400,
    "error": "Bad Request",
    "message": "JSON parse error: Cannot deserialize instance of `java.lang.String` out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.lang.String` out of START_OBJECT token\n at [Source: (PushbackInputStream); line: 2, column: 10] (through reference chain: java.util.HashMap[\"name\"])",
    "path": "/student/filter"
}
显然,我知道后端将“name”视为,其余部分视为


如何在此处使用“firstName”或“lastName”属性筛选数据?更一般地说,如何使用类属性或另一个类中某个类的属性筛选数据?

您的映射在rest控制器中未正确反序列化。 而不是使用HashMap

尝试使用Student类作为请求主体,或者使用com.fasterxml.jackson.databind.node.ObjectNode之类的内容并读取值

public ResponseEntity<?> getFilteredList(@RequestBody ObjectNode req)
为了满足您的需要,我认为您应该了解QueryDsl,它非常好,您可以使用GET request student/filter?name.firstname=xxx进行查询,您有很好的示例

您只需在StudentRepository中扩展QuerydslPredicateExecutor:

import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface StudentRepository extends PagingAndSortingRepository<Student, String>, QuerydslPredicateExecutor<Student> {
}
import org.springframework.data.querydsl.querydsl谓词执行器;
导入org.springframework.data.repository.paging和sortingrepository;
导入org.springframework.stereotype.Repository;
@存储库
公共接口StudentRepository扩展了分页和排序存储库QueryDSL谓词执行器{
}
然后使用谓词进行查询:

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.querydsl.binding.QuerydslPredicate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.function.Predicate;

@CrossOrigin()
@RestController
public class StudentController {
    StudentRepository studentService;

    public StudentController(StudentRepository studentService) {
        this.studentService = studentService;
    }

    @GetMapping("student/filter")
    public ResponseEntity<Page<Student>> getFilteredList(@QuerydslPredicate(root = Student.class) Predicate predicate, Pageable pageable) {
        System.out.println("Something");

        MultiValueMap<String, String> multiValueMap = new LinkedMultiValueMap<>();
        multiValueMap.add("requestedBy", "Shamin Asfaq");

        Page<Student> studentList = studentService.findAll(predicate, pageable);
        return new ResponseEntity<>(studentList, multiValueMap, HttpStatus.OK);
    }
}
import org.springframework.data.domain.Page;
导入org.springframework.data.domain.Pageable;
导入org.springframework.data.querydsl.binding.querydsl谓词;
导入org.springframework.http.HttpStatus;
导入org.springframework.http.ResponseEntity;
导入org.springframework.util.LinkedMultiValueMap;
导入org.springframework.util.MultiValueMap;
导入org.springframework.web.bind.annotation.*;
导入java.util.List;
导入java.util.function.Predicate;
@交叉原点()
@RestController
公共班级学生控制员{
学生就业服务;
公共学生控制员(学生就业学生服务){
this.studentService=studentService;
}
@GetMapping(“学生/过滤器”)
public ResponseEntity getFilteredList(@QuerydslPredicate(root=Student.class)谓词谓词,可分页可分页){
System.out.println(“某物”);
MultiValueMap MultiValueMap=新链接的MultiValueMap();
添加(“requestedBy”、“Shamin Asfaq”);
Page studentList=studentService.findAll(谓词,可分页);
返回新的ResponseEntity(studentList、multiValueMap、HttpStatus.OK);
}
}
您还需要将此构建插件添加到pom.xml中:

        <plugin>
            <groupId>com.mysema.maven</groupId>
            <artifactId>apt-maven-plugin</artifactId>
            <version>${apt.version}</version>
            <dependencies>
                <dependency>
                    <groupId>com.querydsl</groupId>
                    <artifactId>querydsl-apt</artifactId>
                    <version>${querydsl.version}</version>
                </dependency>
            </dependencies>
            <executions>
                <execution>
                    <phase>generate-sources</phase>
                    <goals>
                        <goal>process</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>target/generated-sources/annotations</outputDirectory>
                        <processor>org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor</processor>
                        <logOnlyOnError>true</logOnlyOnError>
                    </configuration>
                </execution>
            </executions>
        </plugin>

com.mysema.maven
aptmaven插件
${apt.version}
com.querydsl
querydsl公寓
${querydsl.version}
生成源
过程
目标/生成的源/注释
org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor
真的

我已经介绍了您建议的两种方法。虽然QueryDsl看起来更好,但更改JSON对我来说更容易实现我想要做的事情。特别是,因为我不需要改变我的任何后端。真是帮了大忙,谢谢!
{
    "timestamp": "2018-08-09T12:01:58.620+0000",
    "status": 400,
    "error": "Bad Request",
    "message": "JSON parse error: Cannot deserialize instance of `java.lang.String` out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.lang.String` out of START_OBJECT token\n at [Source: (PushbackInputStream); line: 2, column: 10] (through reference chain: java.util.HashMap[\"name\"])",
    "path": "/student/filter"
}
public ResponseEntity<?> getFilteredList(@RequestBody ObjectNode req)
{
    "name.firstname":"aaa"
}
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface StudentRepository extends PagingAndSortingRepository<Student, String>, QuerydslPredicateExecutor<Student> {
}
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.querydsl.binding.QuerydslPredicate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.function.Predicate;

@CrossOrigin()
@RestController
public class StudentController {
    StudentRepository studentService;

    public StudentController(StudentRepository studentService) {
        this.studentService = studentService;
    }

    @GetMapping("student/filter")
    public ResponseEntity<Page<Student>> getFilteredList(@QuerydslPredicate(root = Student.class) Predicate predicate, Pageable pageable) {
        System.out.println("Something");

        MultiValueMap<String, String> multiValueMap = new LinkedMultiValueMap<>();
        multiValueMap.add("requestedBy", "Shamin Asfaq");

        Page<Student> studentList = studentService.findAll(predicate, pageable);
        return new ResponseEntity<>(studentList, multiValueMap, HttpStatus.OK);
    }
}
        <plugin>
            <groupId>com.mysema.maven</groupId>
            <artifactId>apt-maven-plugin</artifactId>
            <version>${apt.version}</version>
            <dependencies>
                <dependency>
                    <groupId>com.querydsl</groupId>
                    <artifactId>querydsl-apt</artifactId>
                    <version>${querydsl.version}</version>
                </dependency>
            </dependencies>
            <executions>
                <execution>
                    <phase>generate-sources</phase>
                    <goals>
                        <goal>process</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>target/generated-sources/annotations</outputDirectory>
                        <processor>org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor</processor>
                        <logOnlyOnError>true</logOnlyOnError>
                    </configuration>
                </execution>
            </executions>
        </plugin>