如何在MongoTemplate中使用类属性过滤数据?

时间:2018-08-09 12:20:07

标签: java spring-boot mongotemplate

我第一次使用MongoTemplate。 使用Postman,我要访问API,并以JSON作为@RequestBody传递以获取学生的过滤列表。

模型类

  

Student.java

<script>
    setTimeout(function reload() {location.reload()}, 2000)
</script>
  

Name.java

package bd.ac.seu.erp.criteriademo.model;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;

import javax.validation.constraints.NotNull;

@Data
@NoArgsConstructor
@EqualsAndHashCode
public class Student {
    @Id
    String studentId;

    @NotNull
    Name name;

    String nationality;

}

控制器

  

StudentController.java

package bd.ac.seu.erp.criteriademo.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Name {
    private String firstName;
    private String lastName;
}

服务

  

StudentService.java

package bd.ac.seu.erp.criteriademo.Controller;

import bd.ac.seu.erp.criteriademo.Service.StudentService;
import bd.ac.seu.erp.criteriademo.model.Student;
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.HashMap;
import java.util.List;

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

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

    @PostMapping("student/filter")
    public ResponseEntity<?> getFilteredList(@RequestBody HashMap<String, String> fieldValueMap) {
        System.out.println("Something");

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

        List<Student> studentList = studentService.applyFilter(fieldValueMap);
        return new ResponseEntity<>(studentList, multiValueMap, HttpStatus.OK);
    }
}

当我通过邮递员访问API时,通常这就是我作为@RequestBody发送的内容:

package bd.ac.seu.erp.criteriademo.Service;

import bd.ac.seu.erp.criteriademo.model.Student;
import com.mongodb.MongoClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

@Service
public class StudentService {

    @Value("${spring.data.mongodb.database}")
    String databaseName;

    public List<Student> applyFilter(HashMap<String,String> fieldValueMap) {

        MongoTemplate mongoTemplate = new MongoTemplate(new MongoClient("127.0.0.1"), databaseName);

        Query query = new Query();

        for(Map.Entry<String,String> keyValuePair: fieldValueMap.entrySet()) {
            query.addCriteria(Criteria.where(keyValuePair.getKey()).is(keyValuePair.getValue()));
        }

        return mongoTemplate.find(query, Student.class);
    }
}

..并且工作正常。 当我尝试使用“ firstName”或“ lastName”属性过滤数据时,问题就开始了。

这是我尝试发送的:

{
    "nationality":"Bangladeshi"
}

我从邮递员那里得到的回报是:

{
    "name": {
        "firstName": "Shamin"
    }
}

很显然,我了解到后端正在将“名称”视为,其余部分则视为

如何在此处使用“名字”或“姓氏”属性过滤数据?为了更通用,如何使用类属性或另一个类中一个类的属性来过滤数据?

1 个答案:

答案 0 :(得分:0)

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

尝试将Student类用作请求正文,或使用com.fasterxml.jackson.databind.node.ObjectNode之类的东西并读取值。

Regex.Replace()

或将Json更改为:

public ResponseEntity<?> getFilteredList(@RequestBody ObjectNode req)

对于您的需求,我认为您应该看一下QueryDsl,它非常好,并且您可以使用GET请求Student / filter?name.firstname = xxx进行查询,您有不错的示例link

您只需要在StudentRepository中扩展QuerydslPredicateExecutor:

{
    "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> {
}

您还需要将此构建插件添加到pom.xml:

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);
    }
}