I have 2 documents, ShopDocument and ProductDocument. What i need is to filter out all shops that have field hidden
and removed
equals to true
, from shops that left filter out products that have removed
and hidden
fields equal to true
, then from whats left, i want to filter out shops and products that doesnt match certain string (the matching needs to be in certain fields) and sort the results according to score that i will give to each field (like in lucene). This is my documents:
@Document(indexName = Indices.SHOP_INDEX) @Setting(settingPath = Constants.esSettingsPath) @Data public class ShopDocument { @Id @Field(type = FieldType.Keyword) private Long id; @Field(type = FieldType.Keyword) private Long companyId; @Field(type = FieldType.Boolean) private Boolean companyHidden; @Field(type = FieldType.Keyword) private String slug; @Field(type = FieldType.Keyword) private String postalCode; @Field(type = FieldType.Keyword) private String addressLine; @Field(type = FieldType.Boolean) private boolean hidden; @Field(type = FieldType.Boolean) private boolean removed; @Field(type = FieldType.Text) private String name; @Field(type = FieldType.Nested) private List<ProductDocument> products = new ArrayList<>(); @Field(type = FieldType.Double) private Double latitude; @Field(type = FieldType.Double) private Double longitude; @Field(type = FieldType.Integer) private Integer maxDeliveryDistance; } @Document(indexName = Indices.Product_INDEX) @Setting(settingPath = Constants.esSettingsPath) @Data public class ProductDocument { @Id @Field(type = FieldType.Keyword) private String id; @Field(type = FieldType.Text) private String name; @Field(type = FieldType.Text) private String description; @Field(type = FieldType.Boolean) private boolean hidden; @Field(type = FieldType.Boolean) private boolean removed; @Field(type = FieldType.Long) private Long oldPrice; @Field(type = FieldType.Long) private Long price;
I had tried the following:
BoolQueryBuilder builder = boolQuery(); builder.must(termQuery("hidden", false)) .must(termQuery("removed", false)) .must(nestedQuery("products", termQuery("products.hidden", false), ScoreMode.None)) .must(nestedQuery("products", termQuery("products.removed", false), ScoreMode.None)); SearchHits<ShopDocument> searchHits = operations.search(qb.build(), ShopDocument.class, IndexCoordinates.of(Indices.SHOP_INDEX));
This query should return all shops with hidden
and removed
equals to false
and all products in shops that have hidden
and removed
equals to false
but it only filters out shops and leaves the products as is. Thanks in advance!
Advertisement
Answer
You have to call the method innerHits
of class NestedQueryBuilder
.
This method retrieves just the nested objects that match.
Therefore your code becomes:
BoolQueryBuilder builder = boolQuery(); builder.must(termQuery("hidden", false)) .must(termQuery("removed", false)) .must(nestedQuery("products", termQuery("products.hidden", false), ScoreMode.None).innerHits(new InnerHitBuilder())); .must(nestedQuery("products", termQuery("products.removed", false), ScoreMode.None).innerHits(new InnerHitBuilder())); SearchHits<ShopDocument> searchHits = operations.search(qb.build(), ShopDocument.class, IndexCoordinates.of(Indices.SHOP_INDEX));