Binary
Binary

Reputation: 57

"UncategorizedElasticsearchException": [es/search] failed: [x_content_parse_exception] [1:98] [bool] failed to parse field [should]

versions used:

Spring Data Elasticsearch = 5.0.4

Elasticsearch = 8.5.3

Spring Boot = 3.0.5

Product index:

@AllArgsConstructor
@Data
@Document(indexName = "product", versionType = Document.VersionType.INTERNAL)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Product {

    @Id
    @NotEmpty
    @Field(type = FieldType.Keyword)
    private String id;
    @NotEmpty
    @Field(type = FieldType.Keyword)
    private String brand;
    @NotEmpty
    @Field(type = FieldType.Keyword)
    private String name;
    @NotNull
    @PositiveOrZero
    @Field(type = FieldType.Float)
    private Float price;
    @NotEmpty
    @Field(type = FieldType.Keyword)
    private String category;
    @Field(type = FieldType.Keyword, name = "image_url")
    private String imageURL;
    @NotNull
    @PositiveOrZero
    @Field(type = FieldType.Long)
    private Long stock;
    @NotNull
    @Field(type = FieldType.Text, analyzer = "english")
    private String description;
}

Products repository:

public interface ProductRepository extends ElasticsearchRepository<Product, String> {


    @Query("{\"bool\":{\"should\":[{\"wildcard\":{\"name\":\"*?0*\"}},{\"term\":{\"category\":\"?1\"}},{\"terms\":{\"brand\": ?2}},{\"range\":{\"price\":{\"gte\":?3,\"lte\":?4}}}]}}")
    Page<Product> productSearch(String name, String category, List<String> brands,
                                Integer priceMin, Integer priceMax, Pageable pageable);
   


}

Products mapping:

{
  "product": {
    "mappings": {
      "properties": {
        "_class": {
          "type": "keyword",
          "index": false,
          "doc_values": false
        },
        "brand": {
          "type": "keyword"
        },
        "category": {
          "type": "keyword"
        },
        "description": {
          "type": "text",
          "analyzer": "english"
        },
        "id": {
          "type": "keyword"
        },
        "image_url": {
          "type": "keyword"
        },
        "name": {
          "type": "keyword"
        },
        "price": {
          "type": "float"
        },
        "stock": {
          "type": "long"
        }
      }
    }
  }
}

I'm new to Elasticsearch and I'm learning it by making a small ecommerce website. I am having a problem implementing the above search query. The query works when I execute it trough Kibana console. One thing to note is that I do pass null values of brands, name and category, but I believe I read somewhere that it then ignores those values? Not absolutely sure. that could be the problem. I hope someone can help me thanks.

EDIT: I've figured out that the problem is with the brands terms part of the search query. I want the search to ignore the brands field if it's empty. how do I do that?

Upvotes: 0

Views: 510

Answers (1)

rabbitbr
rabbitbr

Reputation: 3271

You can add some changes for you to take advantage of the maximum performance as a cache in your query. The filters that you have in the "should" clause you can put in the "filter" clause. If you have an empty Brand list you can have another method that runs the productSearch method without the Brand list. In this case you would have two queries, one with the list and one without.

The query I suggest would be this:

{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "category": "?1"
          }
        },
        {
          "terms": {
            "brand": [
              "VALUE1",
              "VALUE2"
            ]
          }
        },
        {
          "range": {
            "price": {
              "gte": "?3",
              "lte": "?4"
            }
          }
        }
      ],
      "must": [
        {
          "wildcard": {
            "name": "*?0*"
          }
        }
      ]
    }
  }
}

Upvotes: 1

Related Questions