Nested是一種嵌套文檔,類似於父子文檔,它可以將與主文檔有關的數據進行存儲,可以把它理解成一張子表
,它的查詢和聚合性能很好;更新性能一般。
下面是測試使用的數據結構,一個包含Nested屬性的實體
@Document(indexName = "esdto", type = "esdto")
@Data
@ToString(callSuper = true)
@AllArgsConstructor
@NoArgsConstructor
public class TestEsDto extends EsBaseEntity implements Serializable {
@Field(type = FieldType.Keyword)
private String name;
private Integer age;
@Field(type = FieldType.Keyword)
private String sex;
@Field(type = FieldType.Keyword)
private String desc;
@Field(type = FieldType.Nested)
private List<Person> personList;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public static class Person {
private Integer age;
@Field(type = FieldType.Keyword)
private String sex;
@Field(type = FieldType.Keyword)
private String desc;
}
}
存儲的數據如圖
聚合代碼
// 創建一個查詢條件對象
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
// 拼接查詢條件
queryBuilder.should(QueryBuilders.termQuery("creator", "1"));
// 嵌套聚合
AbstractAggregationBuilder aggregation =
AggregationBuilders
.nested("personList", "personList")
.subAggregation(AggregationBuilders
.terms("sex").field("personList.sex")
.subAggregation(
AggregationBuilders
.terms("desc").field("personList.desc")
.subAggregation(
AggregationBuilders
.sum("ageSum").field("personList.age")
)
)
);
// 創建查詢對象
SearchQuery build = new NativeSearchQueryBuilder()
.withQuery(queryBuilder) //添加查詢條件
.addAggregation(aggregation) // 添加聚合條件
.withPageable(PageRequest.of(0, 1)) //符合查詢條件的文檔分頁,如果文檔比較大,可以把這個分頁改小(不是聚合的分頁)
.build();
// 執行查詢
AggregatedPage<TestEsDto> testEntities = elasticsearchTemplate.queryForPage(build, TestEsDto.class);
// 取出聚合結果
Nested agg = testEntities.getAggregations().get("personList");
Terms terms = agg.getAggregations().get("sex");
// 遍歷
for (Terms.Bucket bucket : terms.getBuckets()) {
Terms descTerms = bucket.getAggregations().get("desc");
for (Terms.Bucket descTermsBucket : descTerms.getBuckets()) {
ParsedSum parsedSum = descTermsBucket.getAggregations().get("ageSum");//注意從bucket而不是searchResponse
System.out.println(bucket.getKeyAsString() + "\t" +
bucket.getDocCount() + "\t" +
descTermsBucket.getKeyAsString() + "\t" +
parsedSum.getValueAsString());
}
}