Max Gabderakhmanov
Max Gabderakhmanov

Reputation: 922

Correct SearchQuery for few parameters - Elasticsearch & Spring Boot

I'm new in Elasticsearch. I'm trying to create search in Spring Boot application using ES and I stuck with queries in ES.

This is how my app looks like.

Model:

@Entity
@Document(indexName = "sport", type = "sport")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Sport {

   @Id
   @GeneratedValue
   private Long id;

   @Column(length = 256)
   private String name;

}

search method in service:

@GetMapping(value = "/findSportByNameAndId/{name}/{id}")
public List<Sport> findSportByNameAndId(@PathVariable String name, @PathVariable String id){

    SearchQuery searchQuery = new NativeSearchQueryBuilder()
            .withQuery(matchQuery("name", name)
                    .operator(AND)
                    .fuzziness(Fuzziness.TWO)
                    .prefixLength(3))
            .withQuery(matchQuery("id", id)
                    .operator(AND))
            .build();

    List<Sport> sports = operations.queryForList(searchQuery, Sport.class);
    return sports;
}

part of ES index according the model above:

"content": [
    {
        "id": 2,
        "name": "Muay Thai"
    },
    {
        "id": 1,
        "name": "Kickboxing"
    },
    {
        "id": 3,
        "name": "Boxing"
    }
],

When I try to find something with using the name parameter it always stick to id and ignore name. Like This:

enter image description here

How SearchQuery should look like to find Sport by name within id?

Upvotes: 1

Views: 313

Answers (2)

apt-get_install_skill
apt-get_install_skill

Reputation: 2908

You're basically doing two searches; the first one with the name parameter and the second one (which overrides the first one) with the id. The boolean operator (in this case AND) is useless unless you use the bool query.

Upvotes: 1

Max Gabderakhmanov
Max Gabderakhmanov

Reputation: 922

Finally, I have realized how to solve it. In this case I need to use QueryBuilder to specify each parameter:

@GetMapping(value = "/findSportByNameAndId/{name}/{id}")
public List<Sport> findSportByNameAndId(@PathVariable String name, @PathVariable String id){

    QueryBuilder qb = QueryBuilders.boolQuery()
            .must(QueryBuilders.matchQuery("name", name)
                    .operator(AND)
                    .fuzziness(Fuzziness.TWO)
                    .prefixLength(3)
            )
            .filter(QueryBuilders.termQuery("id", id));

    SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(qb).build();

    List<Sport> sports = operations.queryForList(searchQuery, Sport.class);
    return sports;
}

Upvotes: 0

Related Questions