当前位置: 代码迷 >> 综合 >> [乐优商城学习记录]DAY11 Elasticsearch入门
  详细解决方案

[乐优商城学习记录]DAY11 Elasticsearch入门

热度:70   发布时间:2023-09-27 02:02:23.0

参考

https://zhuanlan.zhihu.com/learn4fun
安装步骤

docker pull elasticsearch:6.8.8

docker run -d --restart=always --privileged=true
-v /root/elk/elasticsearch/plugins:/usr/share/elasticsearch/plugins
-e “ES_JAVA_OPTS=-Xms256m -Xmx256m” --name elasticsearch
-p 9200:9200 -p 9300:9300
-e “discovery.type=single-node” elasticsearch:6.8.8

docker exec -it elasticsearch /bin/bash

vi config/elasticsearch.yml

cluster.name: "elasticsearch" 
network.host: 0.0.0.0 
http.cors.enabled: true 
http.cors.allow-origin: "*"

exit
docker restart elasticsearch

[乐优商城学习记录]DAY11 Elasticsearch入门

安装Kibana(基于Node.js的Elasticsearch索引库数据统计工具,可以利用Elasticsearch的聚合功能,生成各种图表,如柱形图,线状图,饼图等)
安装ElasticSearch Head
安装IK分词器

[乐优商城学习记录]DAY11 Elasticsearch入门
[乐优商城学习记录]DAY11 Elasticsearch入门
基础语法
1索引
1.1创建索引
1.2查看单个索引
1.3查看所有索引
1.4删除索引
2映射
2.1创建映射字段
2.1.1type

  1. string(text keyword)
  2. 数字
    2.1.2index
    2.1.3store
    2.1.4boost

2.2查看映射关系
3数据
3.1插入数据 指定id 随机id
3.2修改数据
3.3删除数据


索引就类似建表
映射就类似一些字段约束
添加数据 就类似插入一行
4查询
4.1查询所有
4.2匹配查询(单字段)
match`类型查询,默认会把查询条件进行分词,然后进行查询,多个词条之间是or的关系
“operator”: “and” 可以改成and关系
介于二者之间的"minimum_should_match": “75%”
4.3多字段查询(multi_match)
在2个字段之间查找
4.4词条匹配(term)
4.5多词条精确匹配(terms)
5结果过滤
5.1 指定返回的字段
5.2 包含 或者排除
6高级查询
6.1布尔组合
must must_not should
6.2范围查询(range)
6.3模糊查询(fuzzy)
7过滤
查询会有评分,先查询好,确定好评分,然后再过滤
8排序

聚合aggregations

聚合,包含多种类型,最常用的两种,一个叫,一个叫度量

1桶

桶的作用,是按照某种方式对数据进行分组
每一组数据在ES中称为一个,例如我们根据国籍对人划分,可以得到中国桶英国桶日本桶……或者我们按照年龄段对人进行划分:0-10,10-20,20-30,30-40等
桶的定义,某组具有共同特征的数据
划分桶的方式:
日期阶梯分组
数值阶梯分组
根据词条内容分组 group by
数值和日期的范围分组
桶只负责对数据进行分组,并不进行计算
bucket中往往会嵌套另一种聚合:metrics aggregations即度量

2度量

分组完成以后,我们一般会对组中的数据进行聚合运算,例如求平均值、最大、最小、求和等,这些在ES中称为度量
注意事项:在ES中,需要进行聚合、排序、过滤的字段其处理方式比较特殊,因此不能被分词…字段设置为keyword类型,这个类型不会被分词,将来就可以参与聚合

3聚合为桶

GET /cars/_search
{"size" : 0,"aggs" : { "popular_colors" : { "terms" : { "field" : "color"}}}
}

4桶内度量

GET /cars/_search
{"size" : 0,"aggs" : { "popular_colors" : { "terms" : { "field" : "color"},"aggs":{"avg_price": { "avg": {"field": "price" }}}}}
}

5桶内嵌套桶

GET /cars/_search
{"size" : 0,"aggs" : { "popular_colors" : { "terms" : { "field" : "color"},"aggs":{"avg_price": { "avg": {"field": "price" }},"maker":{"terms":{"field":"make"}}}}}
}

6阶梯分桶Histogram

GET /cars/_search
{"size":0,"aggs":{"price":{"histogram": {"field": "price","interval": 5000}}}
}

Spring Data Elasticsearch

Spring Data通过注解来声明字段的映射属性,有下面的三个注解:

  • @Document 作用在类,标记实体类为文档对象,一般有四个属性
    • indexName:对应索引库名称
    • type:对应在索引库中的类型
    • shards:分片数量,默认5
    • replicas:副本数量,默认1
  • @Id 作用在成员变量,标记一个字段作为id主键
  • @Field 作用在成员变量,标记为文档的字段,并指定字段映射属性:
    • type:字段类型,取值是枚举:FieldType
    • index:是否索引,布尔类型,默认是true
    • store:是否存储,布尔类型,默认是false
    • analyzer:分词器名称:ik_max_word

示例:

@Document(indexName = "item",type = "docs", shards = 1, replicas = 0)
public class Item {@Idprivate Long id;@Field(type = FieldType.Text, analyzer = "ik_max_word")private String title; //标题@Field(type = FieldType.Keyword)private String category;// 分类@Field(type = FieldType.Keyword)private String brand; // 品牌@Field(type = FieldType.Double)private Double price; // 价格@Field(index = false, type = FieldType.Keyword)private String images; // 图片地址
}

代码示例

	@Autowiredprivate ElasticsearchTemplate elasticsearchTemplate;@Testpublic void testCreate(){// 创建索引,会根据Item类的@Document注解信息来创建elasticsearchTemplate.createIndex(Item.class);// 配置映射,会根据Item类中的id、Field等字段来自动完成映射elasticsearchTemplate.putMapping(Item.class);//删除索引elasticsearchTemplate.deleteIndex("heima");

写接口 实现行的增删改查

public interface ItemRepository extends ElasticsearchRepository<Item,Long> {
}

用法类似jpa

高级查询

1 基本查询

	// 词条查询MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("title", "小米");// 执行查询Iterable<Item> items = this.itemRepository.search(queryBuilder);items.forEach(System.out::println);

2 自定义查询

 	// 构建查询条件NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();// 添加基本的分词查询queryBuilder.withQuery(QueryBuilders.matchQuery("title", "小米"));// 执行搜索,获取结果Page<Item> items = this.itemRepository.search(queryBuilder.build());// 打印总条数System.out.println(items.getTotalElements());// 打印总页数System.out.println(items.getTotalPages());items.forEach(System.out::println);

3 分页查询

	// 构建查询条件NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();// 添加基本的分词查询queryBuilder.withQuery(QueryBuilders.termQuery("category", "手机"));// 初始化分页参数int page = 0;int size = 3;// 设置分页参数queryBuilder.withPageable(PageRequest.of(page, size));// 执行搜索,获取结果Page<Item> items = this.itemRepository.search(queryBuilder.build());// 打印总条数System.out.println(items.getTotalElements());// 打印总页数System.out.println(items.getTotalPages());// 每页大小System.out.println(items.getSize());// 当前页System.out.println(items.getNumber());items.forEach(System.out::println);

4 排序

	NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();// 添加基本的分词查询queryBuilder.withQuery(QueryBuilders.termQuery("category", "手机"));// 排序queryBuilder.withSort(SortBuilders.fieldSort("price").order(SortOrder.DESC));// 执行搜索,获取结果Page<Item> items = this.itemRepository.search(queryBuilder.build());// 打印总条数System.out.println(items.getTotalElements());items.forEach(System.out::println);

聚合

1 聚合为桶

	NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();// 不查询任何结果queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null));// 1、添加一个新的聚合,聚合类型为terms,聚合名称为brands,聚合字段为brandqueryBuilder.addAggregation(AggregationBuilders.terms("brands").field("brand"));// 2、查询,需要把结果强转为AggregatedPage类型AggregatedPage<Item> aggPage = (AggregatedPage<Item>) this.itemRepository.search(queryBuilder.build());// 3、解析// 3.1、从结果中取出名为brands的那个聚合,// 因为是利用String类型字段来进行的term聚合,所以结果要强转为StringTerm类型StringTerms agg = (StringTerms) aggPage.getAggregation("brands");// 3.2、获取桶List<StringTerms.Bucket> buckets = agg.getBuckets();// 3.3、遍历for (StringTerms.Bucket bucket : buckets) {// 3.4、获取桶中的key,即品牌名称System.out.println(bucket.getKeyAsString());// 3.5、获取桶中的文档数量System.out.println(bucket.getDocCount());}

2嵌套聚合,求平均值

	NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();// 不查询任何结果queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null));// 1、添加一个新的聚合,聚合类型为terms,聚合名称为brands,聚合字段为brandqueryBuilder.addAggregation(AggregationBuilders.terms("brands").field("brand").subAggregation(AggregationBuilders.avg("priceAvg").field("price")) // 在品牌聚合桶内进行嵌套聚合,求平均值);// 2、查询,需要把结果强转为AggregatedPage类型AggregatedPage<Item> aggPage = (AggregatedPage<Item>) this.itemRepository.search(queryBuilder.build());// 3、解析// 3.1、从结果中取出名为brands的那个聚合,// 因为是利用String类型字段来进行的term聚合,所以结果要强转为StringTerm类型StringTerms agg = (StringTerms) aggPage.getAggregation("brands");// 3.2、获取桶List<StringTerms.Bucket> buckets = agg.getBuckets();// 3.3、遍历for (StringTerms.Bucket bucket : buckets) {// 3.4、获取桶中的key,即品牌名称  3.5、获取桶中的文档数量System.out.println(bucket.getKeyAsString() + ",共" + bucket.getDocCount() + "台");// 3.6.获取子聚合结果:InternalAvg avg = (InternalAvg) bucket.getAggregations().asMap().get("priceAvg");System.out.println("平均售价:" + avg.getValue());}
  相关解决方案