title: How to filter data using class attributes with MongoTemplate?
body: <p>I'm using MongoTemplate for the first time.
  Using Postman, I am hitting the API and passing a JSON as @RequestBody to get a filtered list of Student.</p>
  
  <p><strong>Model Class</strong></p>
  
  <blockquote>
    <p>Student.java</p>
  </blockquote>
  
  <pre><code>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;
  
  }
  </code></pre>
  
  <blockquote>
    <p>Name.java</p>
  </blockquote>
  
  <pre><code>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;
  }
  </code></pre>
  
  <p><strong>Controller</strong></p>
  
  <blockquote>
    <p>StudentController.java</p>
  </blockquote>
  
  <pre><code>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&lt;?&gt; getFilteredList(@RequestBody HashMap&lt;String, String&gt; fieldValueMap) {
          System.out.println("Something");
  
          MultiValueMap&lt;String, String&gt; multiValueMap = new LinkedMultiValueMap&lt;&gt;();
          multiValueMap.add("requestedBy", "Shamin Asfaq");
  
          List&lt;Student&gt; studentList = studentService.applyFilter(fieldValueMap);
          return new ResponseEntity&lt;&gt;(studentList, multiValueMap, HttpStatus.OK);
      }
  }
  </code></pre>
  
  <p><strong>Service</strong></p>
  
  <blockquote>
    <p>StudentService.java</p>
  </blockquote>
  
  <pre><code>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&lt;Student&gt; applyFilter(HashMap&lt;String,String&gt; fieldValueMap) {
  
          MongoTemplate mongoTemplate = new MongoTemplate(new MongoClient("127.0.0.1"), databaseName);
  
          Query query = new Query();
  
          for(Map.Entry&lt;String,String&gt; keyValuePair: fieldValueMap.entrySet()) {
              query.addCriteria(Criteria.where(keyValuePair.getKey()).is(keyValuePair.getValue()));
          }
  
          return mongoTemplate.find(query, Student.class);
      }
  }
  </code></pre>
  
  <p>When I am hitting the API via Postman, normally this is what I am sending as @RequestBody:</p>
  
  <pre><code>{
      "nationality":"Bangladeshi"
  }
  </code></pre>
  
  <p>..and it's working just fine.
  The problem starts when I am trying to filter data using the "firstName" or "lastName" attribute.</p>
  
  <p>This is what I tried to send:</p>
  
  <pre><code>{
      "name": {
          "firstName": "Shamin"
      }
  }
  </code></pre>
  
  <p>Thre return I am getting from Postman is:</p>
  
  <pre><code>{
      "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"
  }
  </code></pre>
  
  <p>Clearly, I have understood that the backend is considering "name" as <strong>key</strong> and the rest of the portion as <strong>value</strong>.</p>
  
  <p>How can I filter data using "firstName" or "lastName" attribute here? To be more generic, how can I filter data using class attributes or, attributes of a Class within another Class?</p>