elasticsearch JavaAPI 基本使用
程序员文章站
2022-07-05 12:31:20
...
1、以springboot为例,引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>transport-netty3-client</artifactId>
<version>5.6.10</version>
</dependency>
2、application.xml 配置es
spring.elasticsearch.rest.uris=ip:9200
3、建立实体
package com.xxx.model.es;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.util.Date;
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 org.springframework.data.elasticsearch.annotations.GeoPointField;
@Data
@Document(indexName = "xxx", type = "xxx", shards = 1, replicas = 0)
public class xxx implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("id")
@Id
@Field(name = "id", type = FieldType.Keyword, fielddata = true)
private String id;
@ApiModelProperty("标题")
@Field(name = "title", type = FieldType.Text,analyzer = "ik_max_word",searchAnalyzer = "ik_smart")
private String title;
@ApiModelProperty("标题拼音")
@Field(name = "titlePinyin", type = FieldType.Text,analyzer = "pinyin",searchAnalyzer = "pinyin")
private String titlePinyin;
@ApiModelProperty("数组例子")
@Field(name = "arrayDemo", type = FieldType.Text)
private String[] arrayDemo;
@ApiModelProperty("需要用聚合函数,配置fielddata")
@Field(name = "aggDemo", type = FieldType.Text,fielddata = true)
private String aggDemo;
@GeoPointField
@Field(name = "location")
@ApiModelProperty("经纬度例子")
private MyGeoPoint location;
}
4、基本操作
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
@Autowired
private ElasticsearchRestTemplate elasticsearchTemplate;
//创建索引
elasticsearchTemplate.createIndex(SecondHouseIndex.class);
//创建mapping
elasticsearchTemplate.putMapping(SecondHouseIndex.class);
//插入/更新数据 bulkIndex 批量
IndexQuery indexQuery = new IndexQueryBuilder().withId(secondHouseIndex.getId()).withObject(secondHouseIndex)
.build();
elasticsearchTemplate.index(indexQuery);
5、聚合
@Test
public void testAgg() {
//以下操作类似mysql: select * from (select AVG(price) avgPrice,district_id distinctId,sum(price) sumPrice from table group by district_id ) order by avgPrice
//分组字段 排序 true正序/false倒序
TermsAggregationBuilder teamAgg = AggregationBuilders.terms("districtId").field("districtId").order(BucketOrder.aggregation("avgPrice",true));
//求平均值字段
AvgAggregationBuilder avgAgg = AggregationBuilders.avg("avgPrice").field("price");
SumAggregationBuilder sumAgg = AggregationBuilders.sum("sumPrice").field("price");
//求和字段
SearchQuery searchQuery = new NativeSearchQueryBuilder().withIndices("index_name")
.withTypes("typeName").addAggregation(teamAgg.subAggregation(avgAgg).subAggregation(sumAgg))
.build();
Aggregations aggregations = elasticsearchTemplate.query(searchQuery, new ResultsExtractor<Aggregations>() {
@Override
public Aggregations extract(SearchResponse response) {
return response.getAggregations();
}
});
Terms terms = (Terms) aggregations.asMap().get("districtId");
List<Bucket> buckets = (List<Bucket>) terms.getBuckets();
for (Bucket bucket : buckets) {
// districtId 分组字段值
String groupById = bucket.getKeyAsString();
Aggregations resultAgg = bucket.getAggregations();
//平均值obj
ParsedAvg parsedAvg = resultAgg.get("avgPrice");
//求和值obj
ParsedSum parsedSum = resultAgg.get("sumPrice");
System.out.println(
"distinctId=" + groupById + ",avg=" + parsedAvg.getValue() + ",sum=" + parsedSum.getValue());
}
}
6、地理位置查询
//地理位置查询 经纬度+半径
GeoDistanceQueryBuilder geoDistanceQueryBuilder = QueryBuilders.geoDistanceQuery("location").point(77.01D,111.11D).distance(1000,DistanceUnit.KILOMETERS);
//按距离排序
GeoDistanceSortBuilder distanceSortBuilder =
new GeoDistanceSortBuilder("location", 77.01D, 111.11D);
distanceSortBuilder.unit(DistanceUnit.KILOMETERS);
distanceSortBuilder.order(SortOrder.ASC);
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(geoDistanceQueryBuilder).withSort(distanceSortBuilder).build();
7、分页查询
//构造查询条件
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//关键词搜索 返回相关性得分大于60的数据
if (StringUtils.isNotBlank(xx.getTitle())) {
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
boolQuery.should(QueryBuilders
.matchQuery(xxConstants.TITLE, xx.getTitle()).minimumShouldMatch("-60%"));
/// boolQuery.should(QueryBuilders
// .matchQuery(xxConstants.TITLE_PINYIN, searchSecondHouseRO.getTitle()));
}
//数组查询 A为数组类型
if (ArrayUtils.isNotEmpty(xx.getA()) && StringUtils
.isNotBlank(xx.getA()[0])) {
boolQueryBuilder
.must(QueryBuilders.termsQuery(xxConstants.FITMENT, xx.getA()));
}
//普通搜索
if (StringUtils.isNotBlank(xx.getDistrictId())) {
boolQueryBuilder.must(QueryBuilders
.termQuery(xxConstants.DISTRICT_ID, xx.getDistrictId()));
}
//大于小于
if (ArrayUtils.isNotEmpty(xx.getB()) && StringUtils
.isNotBlank(xx.getB()[0])) {
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
for (String b: xx.getgetBoom()) {
if ("4".equals(b)) {
boolQueryBuilder .must(boolQuery.should(QueryBuilders.rangeQuery(xxConstants.B).gte(b)));
} else {
boolQueryBuilder
.must(boolQuery.should(QueryBuilders.termQuery(xxConstants.B, b)));
}
}
}
//范围搜索
boolQueryBuilder.must(QueryBuilders.rangeQuery(xxConstants.PRICE)
.from(xx.getBegin())
.to(xx.getEnd()));
//经纬度+半径distance搜索 lat 纬度 lng经度 字段名location
if (StringUtils.isNotBlank(xx.getDistance()) && StringUtils
.isNotBlank(searchSecondHouseRO.getLat()) && StringUtils.isNotBlank(xx.getLng())) {
GeoDistanceQueryBuilder geoDistanceQueryBuilder =
QueryBuilders.geoDistanceQuery("location")
.point(Double.valueOf(xx.getLat()), Double.valueOf(xx.getLng()))
.distance(xx.getDistance(), DistanceUnit.METERS)
.geoDistance(GeoDistance.ARC);
boolQueryBuilder.must(geoDistanceQueryBuilder);
}
//自定义字段排序
nativeSearchQueryBuilder
.withSort(SortBuilders.fieldSort(xxConstants.SORT).order(SortOrder.DESC));
//相关性得分排序
nativeSearchQueryBuilder.withSort(SortBuilders.scoreSort());
SearchQuery searchQuery
=nativeSearchQueryBuilder.withQuery(boolQueryBuilder).build();
//es当前页从0开始计算
int current = xx.getCurrent();
if (xx.getCurrent() > 0) {
xx.setCurrent(xx.getCurrent() - 1);
}
//分页实体
PageRequest pageRequest = PageRequest.of(xx.getCurrent(), xx.getSize());
//构建分页
if (Objects.nonNull(pageRequest)) {
nativeSearchQueryBuilder.withPageable(pageRequest);
}
AggregatedPage<xxModel> aggregatedPage = elasticsearchTemplate
.queryForPage(searchQuery, xxModel.class);
page.setTotal(aggregatedPage.getTotalElements());
page.setSize(searchSecondHouseRO.getSize());
page.setCurrent(current);
page.setRecords(aggregatedPage.getContent());
page.setPages(aggregatedPage.getTotalPages());
return page;