ElasticSearch 教程
基本Restful接口
创建索引
PUT /student
查询索引
GET student
删除索引
DELETE student
往索引内添加数据
#往student内添加一条id为1的数据 如果_doc/后面不加id,es会帮我们自动是生成
POST student/_doc/1
{
"id":1,
"name":"张三",
"birthday" : "2021-05-23"
}
通过id查询索引内的数据
GET student/_doc/1
查看索引mapping信息
GET student/_mapping
修改索引mapping信息
#索引一旦创建后就不能修改mapping信息,如果要修改只能先删除后重新添加
#删除索引
DELETE student
#创建创建student索引并指定mapping信息
PUT student
{
"mappings" : {
"properties" : {
"birthday" : {
"type" : "date"
},
"id" : {
"type" : "long"
},
"name" : {
"type" : "text",
"analyzer": "ik_max_word",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
删除索引内数据
DELETE student/_doc/1
通过id修改数据
POST /student/_update/1
{
"doc": {
"age":21
}
}
索引内数据搜索
match_all 查询全部
POST /student/_search
{
"query": {
"match_all": {}
}
}
match 分词后匹配查询
POST /student/_search
{
"query": {
"match": {
"name": "张"
}
}
}
term 部分词进行查询
POST /student/_search
{
"query": {
"term": {
"FIELD": {
"value": "张"
}
}
}
}
match_phrase 短语查询(分词后进行查询,并确保查询出来的值是顺序的)
POST /student/_search
{
"query": {
"match_phrase": {
"name": "张"
}
}
}
分词器
分析器(analyzer)都由三种构件块组成的:character filters
, tokenizers
, token filters
。
CharacterFilter: 在一段文本进行分词前,先进行预处理,例如:过滤html标签
Tokenizers: 对文本进行分词
Token Filter: 对分词的结果进行加工,例如大写转小写等
三者顺序: Character Filter => Tokenizers => Token Filter
三者个数::analyzer = CharFilter(0或多个)+ Tokenizer(一个)+TokenFilters(0或多个)
IK 分词器
github: https://github.com/medcl/elasticsearch-analysis-ik
下载(注意版本要和ES保持一致): https://github.com/medcl/elasticsearch-analysis-ik/tags
安装: 下载后放入es根路径/plugins/ik下重启es即可
自定义单词:配置 IKAnalyzer.cfg.xml
更多功能看官网
pinyin 分词器
github: https://github.com/medcl/elasticsearch-analysis-pinyin
下载(注意版本要和ES保持一致): https://github.com/medcl/elasticsearch-analysis-pinyin/tags
安装: 下载后放入es根路径/plugins/pinyin下重启es即可
更多功能看官网
创建索引时指定分词器
PUT student
{
"mappings" : {
"properties" : {
"age" : {
"type" : "integer"
},
"birthday" : {
"type" : "date"
},
"id" : {
"type" : "long"
},
"name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
},
"analyzer" : "my_analysis", #使用我们自己的分词器
"search_analyzer": "my_search_analysis"#搜索时使用我们自己的分词器
}
}
},
"settings" : {
"analysis": {
"analyzer": {
"my_analysis":{
"type":"custom",
"tokenizer":"ik_max_word",
"filter":"pinyin_filter"
},
"my_search_analysis":{
"type":"custom",
"tokenizer":"ik_smart",
"filter":"pinyin_filter"
}
},
"filter": {
"pinyin_filter":{
"type":"pinyin",
"keep_first_letter":true
}
}
}
}
}
聚合
案例
文档详情
{
"spu_id" : "570634024130",
"sku_id" : "3711536313345",
"spu_name" : "MINISO名创优品 针线百宝箱家用手提便携针线盒缝补线卷工具组合",
"sku_name" : "颜色分类:白色",
"content" : "和此卖家交流,自觉七经八脉为之一畅,我在淘宝买了这么多年,所谓看过"女干"商无数,但与卖家您交流,我只想说,老板你实在是太好了。 你的高尚情操太让人感动了。本人对此卖家之仰慕如滔滔江水连绵不绝,海枯石烂,天崩地裂,永不变心。交易成功后,我的心情竟是久久不能平静。自古英雄出少年,卖家年纪轻轻,就有经天纬地之才,定国安邦之智,而今,天佑我大中华,沧海桑田5000年,神州平地一声雷,飞沙走石,大雾迷天,朦胧中,只见顶天立地一金甲天神立于天地间,花见花开,人见人爱,这人英雄手持双斧,二目如电,一斧下去,混沌初开,二斧下去,女娲造人,三斧下去,小生倾倒。得此大英雄,实乃国之幸也,民之福,人之初也,怎不叫人喜极而泣 .......看着交易成功,我竟产生出一种无以名之的悲痛感——啊,这么好的卖家,如果将来我再也遇不到了,那我该怎么办?直到我毫不犹豫地把卖家的店收藏了,我内心的那种激动才逐渐平静下来。可是我立刻想到,这么好的卖家,倘若别人看不到,那么不是浪费心血吗?经过痛苦的思想斗争,我终于下定决心,牺牲小我,奉献大我。我要以此评价奉献给世人赏阅,我要给好评……",
"L_cat" : "生活百货",
"L_cat_code" : "20",
"M_cat" : "生活百货",
"M_cat_code" : "2001",
"S_cat" : "居家日用",
"S_cat_code" : "200155",
"XS_cat" : "缝纫",
"XS_cat_code" : "10020102",
"platform_level1" : "天猫",
"platform_level2" : "天猫旗舰店",
"brand" : "天猫",
"sku_url" : "https://detail.tmall.com/item.htm?id=570634024130&skuId=3711536313345",
"sku_img" : [
"https://img.alicdn.com/bao/uploaded/i2/3459177618/O1CN01GZsdbg2695sAJX2dn_!!0-item_pic.jpg"
],
"publish_time" : "2019-08-02 10:38:00",
"XS_cat_search" : "缝纫",
"feature_sa" : [
{
"feature_level1" : "购买体验",
"feature_level2" : "店铺",
"feature_word" : "卖家",
"evalute_word" : "好",
"sentiment" : 1
},
{
"feature_level1" : "产品体验",
"feature_level2" : "观感",
"feature_word" : "看着",
"evalute_word" : "成功",
"sentiment" : 1
}
]
}
1 查询 S_cat_code为 200155 的商品本月评论总数
GET yuqing_koubei/_search
{
"query": {
"bool":{
"must": [
{"term": {
"S_cat_code": {
"value": "200155"
}
}},
{
"range": {
"publish_time": {
"gte": "2021-05-01 00:00:00",
"lte": "2021-05-27 00:00:00"
}
}
}
]
}
},
"aggs": {
"value_count": {
"value_count":{
"field": "_id"
}
}
},
"size": 0
}
2 查询 S_cat_code为 200155 商品近6个月每个月的评论数量
GET yuqing_koubei/_search
{
"query": {
"bool":{
"must": [
{"term": {
"S_cat_code": {
"value": "200155"
}
}},
{
"range": {
"publish_time": {
"gte": "2021-05-01 00:00:00",
"lte": "2021-05-27 00:00:00"
}
}
}
]
}
},
"aggs": {
"month_count": {
"date_histogram": {
"field": "publish_time",
"interval": "month",
"format": "yyyy-MM-dd"
}
}
},
"size": 0
}
3 查询 S_cat_code为 200155 商品本月好评和差评的数量分别有多少
#由于feature_sa是对象类型的数组必须通过nested查询一遍后才能通过里面的属性判断,
#注意 reverse_nested是跳出 nested查询外面的数据 不然就查询不出来
GET /yuqing_koubei/_search
{
"size": 0,
"_source": [
"feature_sa"
],
"query": {
"bool": {
"must": [
{
"nested": {
"path": "feature_sa",
"query": {
"exists": {
"field": "feature_sa"
}
}
}
},
{
"term": {
"L_cat_code": "25"
}
}
],
"filter": {
"range": {
"publish_time": {
"gte": "now-0M/M",
"lte": "now/M"
}
}
}
}
},
"aggs": {
"feature_sa": {
"nested": {
"path": "feature_sa"
},
"aggs": {
"brands": {
"terms": {
"field": "feature_sa.sentiment"
},
"aggs": {
"rev": {
"reverse_nested": {},
"aggs": {
"cunt_code":{
"terms": {
"field": "L_cat_code"
}
}
}
}
}
}
}
}
}
}
SpringBoot 整合
1 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
2 配置
配置文件配置
spring.elasticsearch.rest.uris=http://localhost:9200
spring.elasticsearch.rest.username=elastic
spring.elasticsearch.rest.password=123
配置类配置
@Configuration
public class EsConfig {
@Bean
public ElasticsearchRestTemplate restTemplate(){
RestClientBuilder builder = RestClient.builder(new HttpHost("2127.0.0.1", 9200));
//设置密码
final BasicCredentialsProvider basicCredentialsProvider = new BasicCredentialsProvider();
basicCredentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("elastic","123"));
builder.setHttpClientConfigCallback(httpAsyncClientBuilder -> httpAsyncClientBuilder.setDefaultCredentialsProvider(basicCredentialsProvider));
RestHighLevelClient restHighLevelClient = new RestHighLevelClient(builder);
return new ElasticsearchRestTemplate(restHighLevelClient);
}
}
创建bean
@Data
@NoArgsConstructor
@AllArgsConstructor
@Document(indexName = "person",shards = 1,replicas = 1)
public class Person {
@Id
private Long id;
@Field(type = FieldType.Text)
private String name;
private Integer age;
private double price;
private String[] tag;
}
通过 Repository 查询
@Repository
public interface PersonMapper extends ElasticsearchRepository<Person,Integer> {
//偶根据方法名动态查询带分页
public Page<Person> findByName(String name, Pageable pageable);
//SpringData ES 通过方法名动态查询 高亮显示
@Highlight(fields = {@HighlightField(name="name",parameters = @HighlightParameters(preTags = "<h1>",postTags = "</h1>"))})
public List<SearchHit<Person>> findByNameIn(List<String> names);
//自定义查询 ?0指定第1个参数 ?1第二个 支持分页
@Query("{\n" +
" \"bool\": {\n" +
" \"must\": [\n" +
" {\n" +
" \"query_string\": {\n" +
" \"query\": \"?0\",\n" +
" \"fields\": [\"name\"],\n" +
" \"default_operator\": \"OR\"\n" +
" }\n" +
" },\n" +
" {\"range\": {\n" +
" \"age\": {\n" +
" \"gt\": ?1\n" +
" }\n" +
" }}\n" +
" ]\n" +
" }\n" +
" }")
public List<Person> querySelf(String name,Integer age);
}
通过ElasticsearchTemplate查询
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
//name为国旗且age between 10 and 20
boolQuery.must(QueryBuilders.matchQuery("name","国旗"));
boolQuery.must( QueryBuilders.rangeQuery("age").gte(10).lte(20) );
NativeSearchQueryBuilder nativeBuilder = new NativeSearchQueryBuilder();
nativeBuilder.withQuery(boolQuery);
//查询 person 索引
SearchHits<Person> person = esRestTemplate.search(nativeBuilder.build(), Person.class, IndexCoordinates.of("person"));
List<Person> collect = person.getSearchHits().stream().map(hit -> hit.getContent()).collect(Collectors.toList());
System.out.println(collect);
聚合查询
查询语句:
GET yuqing_koubei/_search
{
"aggs": {
"value_count": {
"value_count":{
"field": "_id"
}
}
},
"size": 0
}
java 代码
ValueCountAggregationBuilder count = AggregationBuilders.count("count");
count.field("_id");
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
nativeSearchQueryBuilder.addAggregation(count);
nativeSearchQueryBuilder.withPageable(PageRequest.of(0,1));
SearchHits<YuqingKoubei> search = restTemplate.search(nativeSearchQueryBuilder.build(), YuqingKoubei.class, IndexCoordinates.of("yuqing_koubei"));
ParsedValueCount count1 = search.getAggregations().get("count");
System.out.println(count1.getValue());