参考
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
安装Kibana(基于Node.js的Elasticsearch索引库数据统计工具,可以利用Elasticsearch的聚合功能,生成各种图表,如柱形图,线状图,饼图等)
安装ElasticSearch Head
安装IK分词器
基础语法
1索引
1.1创建索引
1.2查看单个索引
1.3查看所有索引
1.4删除索引
2映射
2.1创建映射字段
2.1.1type
- string(text keyword)
- 数字
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());}