引子
全文检索方便快速查询数据
elasticsearch的基本概念
1.Index
类比传统的关系型数据库领域来说,索引相当于SQL中的一个数据库,或者一个数据存储方案。索引由其名称进行标识,并通过引用此名称完成文档的创建、搜索、更新及删除操作。一个ES集群中可以按需创建任意数目的索引。
2.Document
文档是Lucene索引和搜索的原子单位。
许多条 Document 构成了一个 Index,类比传统数据库中的记录条。
3.Type
类型是索引内部的逻辑分区(category/partition),其意义完全取决于用户需求(自定义)。因此,一个索引内部可定义一个或多个类型(type)。类比传统的关系型数据库领域来说,类型相当于“表”。我使用的版本是elasticsearch:7.6.2,已经将Tppe移除了
4.Field
document文档是一个包含了一个或多个域的容器,而域的值则是真正被搜索的内容。每个域都有其标识名称,通常为一个文本值或二进制值。将文档加入索引中时,需要首先将数据转换成Lucene能识别的文档和域,域值是被搜索的对象。例如,用户输入搜索内容“title:elasticsearch”时,则表示搜索“标题”域值中包含单词“elasticsearch”的所有文档。
5.Mapping
ES中,所有的文档在存储之前都要首先进行分析。用户可根据需要定义如何分词,即如何将文本分割成词元(token)、哪些token应该被过滤掉,以及哪些文本需要进行额外处理等等。
elasticsearch简单使用
基本操作引用的是rest风格
PUT test/books/1
records
GET test/books/_search
query_syntax
POST test/books/5/_update
update_syntax
DELETE test/books/id
elasticsearch 简单整合 springboot
引入rest风格的elasticsearch依赖
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.6.2</version>
</dependency>
配置一个elasticsearch-client组件
@Configuration
public class ElasticSearchConfiguration {
public static final RequestOptions COMMON_OPTIONS;
static {
RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
// builder.addHeader("Authorization", "Bearer ");
// builder.setHttpAsyncResponseConsumerFactory(
// new HttpAsyncResponseConsumerFactory
// .HeapBufferedResponseConsumerFactory(30 * 1024 * 1024 * 1024));
COMMON_OPTIONS = builder.build();
}
@Value("${yun.server.host}")
String host;
@Bean
public RestHighLevelClient ElasticSearchClient() {
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost(host, 9200, "http")));
return client;
}
}
保存索引
@Autowired
RestHighLevelClient client;
@Override
public boolean saveSku(List<EsSearchModel> data) throws IOException {
BulkRequest bulkRequest = new BulkRequest();
for (EsSearchModel item : data) {
IndexRequest indexRequest = new IndexRequest(ElasticSearchConstant.UP_SAVE_INDEX);
indexRequest.id(item.getSkuId().toString());
String s = JSON.toJSONString(item);
indexRequest.source(s, XContentType.JSON);
bulkRequest.add(indexRequest);
}
BulkResponse bulk = client.bulk(bulkRequest, ElasticSearchConfiguration.COMMON_OPTIONS);
boolean b = !bulk.hasFailures();
List<String> collect = Arrays.stream(bulk.getItems()).map(item -> item.getId()).collect(Collectors.toList());
log.error("上架完成:{}", collect);
return b;
}
查询记录(包含对elasticsearch的结果集进行处理:过滤、排序、分页、高亮、聚合)
private SearchRequest buildSearchSentence(SearchParam param) {
SearchRequest request = new SearchRequest(ElasticSearchConstant.UP_SAVE_INDEX);
//1.1查询
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
if (!StringUtils.isEmpty(param.getKeyword())) {
boolQuery.must(QueryBuilders.matchQuery("skuTitle", param.getKeyword()));
}
//1.1过滤
if (param.getCatalog3Id() != null) {
boolQuery.filter(QueryBuilders.termQuery("catalogId", param.getCatalog3Id()));
}
if (param.getBrandId() != null && param.getBrandId() > 0) {
boolQuery.filter(QueryBuilders.termQuery("brandId", param.getBrandId()));
}
boolQuery.filter(QueryBuilders.termQuery("hasStock", param.getHasStock() == 1));
if (!StringUtils.isEmpty(param.getSkuPrice())) {
String[] s = param.getSkuPrice().split("_");
if (s.length == 2) {
boolQuery.filter(QueryBuilders.rangeQuery("skuPrice").gte(s[0]).lte(s[1]));
} else if (s.length == 1) {
if (param.getSkuPrice().startsWith("_")) {
boolQuery.filter(QueryBuilders.rangeQuery("skuPrice").lte(s[0]));
} else {
boolQuery.filter(QueryBuilders.rangeQuery("skuPrice").gte(s[0]));
}
}
}
if (!StringUtils.isEmpty(param.getAttrs())) {
for (String attr : param.getAttrs()) {
BoolQueryBuilder nestedQuery = QueryBuilders.boolQuery();
String[] s = attr.split("_");
String attrId = s[0];
nestedQuery.must(QueryBuilders.termQuery("attrs.attrId",attrId));
String[] attrValues = s[1].split(":");
nestedQuery.must(QueryBuilders.termsQuery("attrs.attrValue",attrValues));
NestedQueryBuilder nestedQueryBuilder = QueryBuilders.nestedQuery("attrs", nestedQuery, ScoreMode.None);
boolQuery.filter(nestedQueryBuilder);
}
// boolQuery1.must(QueryBuilders.termQuery("attrs.attrId",param.))
}
sourceBuilder.query(boolQuery);
//1.2排序
if (!StringUtils.isEmpty(param.getSort())) {
String[] s = param.getSort().split("_");
// FieldSortBuilder order = new FieldSortBuilder(s[0]).order(s[1] == "desc" ? SortOrder.DESC : SortOrder.DESC);
// sourceBuilder.sort(order);
SortOrder order = s[1].equalsIgnoreCase("desc") ? SortOrder.DESC : SortOrder.ASC;
sourceBuilder.sort(s[0],order);
}
//1.3分页
if (param.getPageNum() != null && param.getPageNum() > 0) {
// Long pageNum = param.getPageNum();
sourceBuilder.from((param.getPageNum()-1)*ElasticSearchConstant.SEARCH_PAGE_COUNT);
sourceBuilder.size(ElasticSearchConstant.SEARCH_PAGE_COUNT);
}
//1.4高亮
if (!StringUtils.isEmpty(param.getKeyword())) {
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("skuTitle");
highlightBuilder.preTags("<b style='color:red'>");
highlightBuilder.postTags("</b>");
sourceBuilder.highlighter(highlightBuilder);
}
//1.6聚合
TermsAggregationBuilder brandAgg = AggregationBuilders.terms("brandAgg").field("brandId").size(10);
brandAgg.subAggregation(AggregationBuilders.terms("brandNameAgg").field("brandName").size(10));
brandAgg.subAggregation(AggregationBuilders.terms("brandImgAgg").field("brandImg").size(10));
sourceBuilder.aggregation(brandAgg);
TermsAggregationBuilder catalogAgg = AggregationBuilders.terms("catalogAgg").field("catalogId").size(10);
catalogAgg.subAggregation(AggregationBuilders.terms("catalogNameAgg").field("catalogName").size(10));
sourceBuilder.aggregation(catalogAgg);
NestedAggregationBuilder nested = AggregationBuilders.nested("attrs", "attrs");
TermsAggregationBuilder attrIdAgg = AggregationBuilders.terms("attrIdAgg").field("attrs.attrId");
attrIdAgg.subAggregation(AggregationBuilders.terms("attrNameAgg").field("attrs.attrName"));
attrIdAgg.subAggregation(AggregationBuilders.terms("attrValueAgg").field("attrs.attrValue"));
nested.subAggregation(attrIdAgg);
sourceBuilder.aggregation(nested);
System.out.println("dsl" + sourceBuilder.toString());
request.source(sourceBuilder);
return request;
}
其他
欢迎指正与指导!