Skip to content
Advertisement

Full text elasticsearch filltering nested objects and hits order hits by score of the field

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));
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement