分组查询


	private final ElasticsearchRestTemplate esRestTemplate;
	
	// select count(1), status from order group by status 
	public void aggregate(){
		// 查询条件
		NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder()
			.withQuery(
				QueryBuilders.rangeQuery("createTime")
					.format("yyyy-MM-dd HH:mm:ss")
					.gte("2021-08-17 00:00:00").lte("2021-08-18 00:00:00")
					.includeLower(true).includeUpper(true))
			// 分组查询status字段并as count
			.addAggregation(AggregationBuilders.terms("count").field("status"))	
			.withSourceFilter(new FetchSourceFilterBuilder().build())
			// 下面两行优化速度 去除查询结果 只取聚合查询的结果
			// withFields不给参数去掉dom的所有字段 & 分页只取1条
			.withFields()
			.withPageable(PageRequest.of(0, 1));

		String idx = "idx_order_dev";
		AggregatedPage<EsOrder> results = esRestTemplate.queryForPage(queryBuilder.build(), EsOrder.class, IndexCoordinates.of(idx));
		Aggregations entitiesAggregations = results.getAggregations();
		Terms terms = (Terms) entitiesAggregations.asMap().get("count");
		
		// 遍历取出聚合字段列的值,与对应的数量
		for (Terms.Bucket bucket : terms.getBuckets()) {
			String key = bucket.getKeyAsString(); // 聚合字段列的值
			long val = bucket.getDocCount();// 聚合字段对应的数量
			System.out.printf("%s -> %s\n", key, val);
		}
	
	}

索引操作

操作单条保存时 ElasticsearchRestTemplateElasticsearchRepository
因为repository会在每次保存完时刷新索引

  • 创建索引 & 字段映射
IndexCoordinates idx = IndexCoordinates.of("idx_order");
IndexOperations idxOps = esRestTemplate.indexOps(idx);
idxOps.create();
Document mapping = idxOps.createMapping(EsOrder.class);
idxOps.putMapping(mapping);
  • 删除索引(等于drop table 数据全清除)
IndexCoordinates idx = IndexCoordinates.of("idx_order_dev");
IndexOperations idxOps = esRestTemplate.indexOps(idx);
idxOps.delete();
  • 实体类
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;

@Data
@Document(indexName = "idx_order_#{orderConfiguration.profile}", shards = 3, replicas = 2)
public class EsOrder extends EsOrderView implements Serializable {
	/**
	 * 订单号
	 */
	@Field(type = FieldType.Keyword)
	private String orderId;
	...
}

10000条上限

  • 查询条数限制
    query时默认上限是10000条 向ES服务器put一条设置即可修改该限制
PUT /索引名/_settings?preserve_existing=true
{"index.max_result_window":"2000000000"}
  • count限制
    使用ElasticsearchRepository或者ElasticsearchRestTemplate查询分页时,返回的total数也会限制10000,导致分页功能页面仅显示10000条。
    AbstractQuery的源码得知里面有提供字段trackTotalHits用于查询总数,但是builder类NativeSearchQueryBuilder中没有提供设值方法 我们可以在此基础上自定义一个QueryBuilder来设值进去即可。
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

/**
 * 自定义queryBuilder 在原基础上添加了trackTotalHits的配置
 * @author stark
 * @date 2021年11月29日11:32:30
 */
public class NativeSearchQueryBuilderCustom extends NativeSearchQueryBuilder{

	private Boolean trackTotalHits;

	public NativeSearchQueryBuilderCustom() {
	}

	public NativeSearchQueryBuilderCustom trackTotalHits(boolean trackTotalHits) {
		this.trackTotalHits = trackTotalHits;
		return this;
	}

	@Override
	public NativeSearchQueryBuilderCustom withFields(String... fields) {
		super.withFields(fields);
		return this;
	}

	@Override
	public NativeSearchQueryBuilderCustom withQuery(QueryBuilder queryBuilder) {
		super.withQuery(queryBuilder);
		return this;
	}

	@Override
	public NativeSearchQueryBuilderCustom withSort(SortBuilder sortBuilder) {
		super.withSort(sortBuilder);
		return this;
	}

	@Override
	public NativeSearchQueryBuilderCustom withPageable(Pageable pageable) {
		super.withPageable(pageable);
		return this;
	}

	@Override
	public NativeSearchQuery build() {
		NativeSearchQuery build = super.build();
		if(this.trackTotalHits != null){
			build.setTrackTotalHits(this.trackTotalHits);
		}

		return build;
	}
}

使用

NativeSearchQueryBuilderCustom queryBuilder = new NativeSearchQueryBuilderCustom()
			.withPageable(PageRequest.of(query.getCurrent(), query.getSize()))	// 分页
			.withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC))	// 排序
			.withFields(fixedEsField)	// 过滤字段
			.trackTotalHits(true);	// 查询所有数

repository.search(queryBuilder.build());
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐