spring-boot-demo-elasticsearch
此 demo 主要演示了 Spring Boot 如何集成
spring-boot-starter-data-elasticsearch
完成? ElasticSearch 的高?使用技巧,包括?建索引、配置映射、?除索引、增?改?基本操作、????、高???、聚合??等。
作者??本demo?,ElasticSearch版本?
6.5.3
,使用 docker ?行,下面是所有步?:
-
下??像:
docker pull elasticsearch:6.5.3
-
?行容器:
docker run -d -p 9200:9200 -p 9300:9300 --name elasticsearch-6.5.3 elasticsearch:6.5.3
-
?入容器:
docker exec -it elasticsearch-6.5.3 /bin/bash
-
安? ik 分?器:
./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.5.3/elasticsearch-analysis-ik-6.5.3.zip
-
修改 es 配置文件:`vi ./config/elasticsearch.yml
cluster.name
:
"
docker-cluster
"
network.host
:
0.0.0.0
#
minimum_master_nodes need to be explicitly set when bound on a public IP
#
set to 1 to allow single node clusters
#
Details: https://github.com/elastic/elasticsearch/pull/17288
discovery.zen.minimum_master_nodes
:
1
#
just for elasticsearch-head plugin
http.cors.enabled
:
true
http.cors.allow-origin
:
"
*
"
-
退出容器:
exit
-
停止容器:
docker stop elasticsearch-6.5.3
-
??容器:
docker start elasticsearch-6.5.3
<?
xml
version
=
"
1.0
"
encoding
=
"
UTF-8
"
?>
<
project
xmlns
=
"
http://maven.apache.org/POM/4.0.0
"
xmlns
:
xsi
=
"
http://www.w3.org/2001/XMLSchema-instance
"
xsi
:
schemaLocation
=
"
http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd
"
>
<
modelVersion
>4.0.0</
modelVersion
>
<
artifactId
>spring-boot-demo-elasticsearch</
artifactId
>
<
version
>1.0.0-SNAPSHOT</
version
>
<
packaging
>jar</
packaging
>
<
name
>spring-boot-demo-elasticsearch</
name
>
<
description
>Demo project for Spring Boot</
description
>
<
parent
>
<
groupId
>com.xkcoding</
groupId
>
<
artifactId
>spring-boot-demo</
artifactId
>
<
version
>1.0.0-SNAPSHOT</
version
>
</
parent
>
<
properties
>
<
project
.build.sourceEncoding>UTF-8</
project
.build.sourceEncoding>
<
project
.reporting.outputEncoding>UTF-8</
project
.reporting.outputEncoding>
<
java
.version>1.8</
java
.version>
</
properties
>
<
dependencies
>
<
dependency
>
<
groupId
>org.springframework.boot</
groupId
>
<
artifactId
>spring-boot-starter</
artifactId
>
</
dependency
>
<
dependency
>
<
groupId
>org.springframework.boot</
groupId
>
<
artifactId
>spring-boot-starter-data-elasticsearch</
artifactId
>
</
dependency
>
<
dependency
>
<
groupId
>org.springframework.boot</
groupId
>
<
artifactId
>spring-boot-starter-test</
artifactId
>
<
scope
>test</
scope
>
</
dependency
>
<
dependency
>
<
groupId
>org.projectlombok</
groupId
>
<
artifactId
>lombok</
artifactId
>
<
optional
>true</
optional
>
</
dependency
>
<
dependency
>
<
groupId
>cn.hutool</
groupId
>
<
artifactId
>hutool-all</
artifactId
>
</
dependency
>
<
dependency
>
<
groupId
>com.google.guava</
groupId
>
<
artifactId
>guava</
artifactId
>
</
dependency
>
</
dependencies
>
<
build
>
<
finalName
>spring-boot-demo-elasticsearch</
finalName
>
<
plugins
>
<
plugin
>
<
groupId
>org.springframework.boot</
groupId
>
<
artifactId
>spring-boot-maven-plugin</
artifactId
>
</
plugin
>
</
plugins
>
</
build
>
</
project
>
???
@Document 注解主要?明索引名、?型名、分片?量和???量
@Field 注解主要?明字段??ES的?型
/**
* <p>
* 用????
* </p>
*
* @author yangkai.shen
* @date Created in 2018-12-20 17:29
*/
@
Document
(
indexName
=
EsConsts
.
INDEX_NAME
,
type
=
EsConsts
.
TYPE_NAME
,
shards
=
1
,
replicas
=
0
)
@
Data
@
NoArgsConstructor
@
AllArgsConstructor
public
class
Person
{
/**
* 主?
*/
@
Id
private
Long
id
;
/**
* 名字
*/
@
Field
(
type
=
FieldType
.
Keyword
)
private
String
name
;
/**
* ?家
*/
@
Field
(
type
=
FieldType
.
Keyword
)
private
String
country
;
/**
* 年?
*/
@
Field
(
type
=
FieldType
.
Integer
)
private
Integer
age
;
/**
* 生日
*/
@
Field
(
type
=
FieldType
.
Date
)
private
Date
birthday
;
/**
* 介?
*/
@
Field
(
type
=
FieldType
.
Text
,
analyzer
=
"ik_smart"
)
private
String
remark
;
}
/**
* <p>
* 用?持久?
* </p>
*
* @author yangkai.shen
* @date Created in 2018-12-20 19:00
*/
public
interface
PersonRepository
extends
ElasticsearchRepository
<
Person
,
Long
> {
/**
* 根据年?????
*
* @param min 最小?
* @param max 最大?
* @return ?足?件的用?列表
*/
List
<
Person
>
findByAgeBetween
(
Integer
min
,
Integer
max
);
}
主要???建索引、映射配置、?除索引
/**
* <p>
* ?? ElasticTemplate 的?建/?除
* </p>
*
* @author yangkai.shen
* @date Created in 2018-12-20 17:46
*/
public
class
TemplateTest
extends
SpringBootDemoElasticsearchApplicationTests
{
@
Autowired
private
ElasticsearchTemplate
esTemplate
;
/**
* ?? ElasticTemplate ?建 index
*/
@
Test
public
void
testCreateIndex
() {
// ?建索引,?根据Item?的@Document注解信息??建
esTemplate
.
createIndex
(
Person
.
class
);
// 配置映射,?根据Item?中的id、Field等字段?自?完成映射
esTemplate
.
putMapping
(
Person
.
class
);
}
/**
* ?? ElasticTemplate ?除 index
*/
@
Test
public
void
testDeleteIndex
() {
esTemplate
.
deleteIndex
(
Person
.
class
);
}
}
PersonRepositoryTest.java
主要功能,??方法上方注?
/**
* <p>
* ?? Repository 操作ES
* </p>
*
* @author yangkai.shen
* @date Created in 2018-12-20 19:03
*/
@
Slf4j
public
class
PersonRepositoryTest
extends
SpringBootDemoElasticsearchApplicationTests
{
@
Autowired
private
PersonRepository
repo
;
/**
* ??新增
*/
@
Test
public
void
save
() {
Person
person
=
new
Person
(
1L
,
"??"
,
"蜀?"
,
18
,
DateUtil
.
parse
(
"1990-01-02 03:04:05"
),
"??(161年-223年6月10日),??昭烈帝(221年-223年在位),又?先主,字玄德,??末年幽州?郡??(今河北省?州市)人,西?中山靖王??之后,三??期蜀???皇帝、政治家。
\n
??少年?拜?植??;早年?沛流?,???辛,投??多??侯,曾?????巾起?。先后率?救援北海相孔融、徐州牧陶?等。陶?病亡后,?徐州????。赤壁之??,??????盟??曹操,???取?州。而后?取益州。于章武元年(221年)在成都?帝,???,史?蜀或蜀?。《三?志》???的机?干略不及曹操,但其弘毅?厚,知人待士,百折不?,?成帝?。??也?自己做事“每?操反,事乃成?”。
\n
章武三年(223年),??病逝于白帝城,?年六十三?,??昭烈皇帝,??烈祖,葬惠陵。后世有?多文?作品以其?主角,在成都武侯祠有昭烈???念。"
);
Person
save
=
repo
.
save
(
person
);
log
.
info
(
"【save】= {}"
,
save
);
}
/**
* ??批量新增
*/
@
Test
public
void
saveList
() {
List
<
Person
>
personList
=
Lists
.
newArrayList
();
personList
.
add
(
new
Person
(
2L
,
"曹操"
,
"魏?"
,
20
,
DateUtil
.
parse
(
"1988-01-02 03:04:05"
),
"曹操(155年-220年3月15日),字孟德,一名吉利,小字阿?,沛???(今安徽?州)人。??末年杰出的政治家、?事家、文?家、?法家,三?中曹魏政?的奠基人。
\n
曹操曾?任??丞相,后加封魏王,奠定了曹魏立?的基?。去世后???武王。其子曹丕?帝后,追尊?武皇帝,??太祖。
\n
??末年,天下大?,曹操以?天子的名?征?四方,??消?二袁、?布、?表、?超、?遂等割据?力,?外降服南匈奴、?桓、?卑等,?一了中?北方,??行一系列政策恢???生?和社?秩序,?大屯田、?修水利、???桑、重?手工?、安置流亡人口、?行“租?制”,?而使中原社????定、??出??机。?河流域在曹操?治下,政治???明,??逐步恢?,???迫稍有??,社???有所好?。曹操在?朝的名?下所采取的一些措施具有??作用。
\n
曹操?事上精通兵法,重??才,?此不惜一切代价?看中的?能分子收于麾下;生活上善?歌,抒?自己的政治抱?,?反映?末人民的苦?生活,?魄雄?,慷慨悲凉;散文亦?峻整?,???繁?了建安文?,?后人留下了??的精神?富,?迅?价其?“改造文章的祖?”。同?曹操也擅??法,唐朝??瓘在《??》?曹操的章草??“妙品”。"
));
personList
.
add
(
new
Person
(
3L
,
"??"
,
"??"
,
19
,
DateUtil
.
parse
(
"1989-01-02 03:04:05"
),
"??(182年-252年5月21日),字仲?,?郡富春(今浙江杭州富??)人。三??代??的建立者(229年-252年在位)。
\n
??的父???和兄??策,在??末年群雄割据中打下了江?基?。建安五年(200年),?策遇刺身亡,???之掌事,成?一方?侯。建安十三年(208年),???建立???盟,?于赤壁之?中??曹操,奠定三?鼎立的基?。建安二十四年(219年),??派?蒙成功?取??的?州,使?土面?大大增加。
\n
?武元年(222年),??被魏文帝曹丕?封??王,建立??。同年,在夷陵之?中大???。??元年(229年),在武昌正式?帝,???,不久后?都建?。???帝后,?置?官,?行屯田,?置郡?,???剿?山越,促?了江南??的?展。在此基?上,他又多次派人出海。??二年(230年),??派??、?葛直抵?夷州。
\n
???年在?承人??上反?无常,引致群下??,朝局不?。太元元年(252年)病逝,享年七十一?,在位二十四年,??大皇帝,??太祖,葬于?陵。
\n
??亦善?,唐代??瓘在《??》中?其?法列?第三等。"
));
personList
.
add
(
new
Person
(
4L
,
"?葛亮"
,
"蜀?"
,
16
,
DateUtil
.
parse
(
"1992-01-02 03:04:05"
),
"?葛亮(181年-234年10月8日),字孔明,???,徐州琅??都(今山??沂市沂南?)人,三??期蜀?丞相,杰出的政治家、?事家、外交家、文?家、?法家、?明家。
\n
早年?叔父?葛玄到?州,?葛玄死后,?葛亮就在襄?隆中?居。后??三?茅??出?葛亮,??抗曹,于赤壁之?大?曹?。形成三?鼎足之?,又?占?州。建安十六年(211年),攻取益州。?又??曹?,?得?中。蜀章武元年(221年),??在成都建立蜀?政?,?葛亮被任命?丞相,主持朝政。蜀后主???位,?葛亮被封?武?侯,?益州牧。勤勉??,大小政事必?自?理,???明;????盟,改善和西南各族的?系;?行屯田政策,加强??。前后六次北伐中原,多以粮?无功。?因??成疾,于蜀建?十二年(234年)病逝于五丈原(今?西??岐山境?),享年54?。??追封其?忠武侯,后世常以武侯尊??葛亮。?晋政?因其?事才能特追封他?武?王。
\n
?葛亮散文代表作有《出?表》《?子?》等。曾?明木牛流?、孔明?等,?改造?弩,叫做?葛?弩,可一弩十矢俱?。?葛亮一生“鞠躬??、死而后已”,是中???文化中忠臣?智者的代表人物。"
));
Iterable
<
Person
>
people
=
repo
.
saveAll
(
personList
);
log
.
info
(
"【people】= {}"
,
people
);
}
/**
* ??更新
*/
@
Test
public
void
update
() {
repo
.
findById
(
1L
).
ifPresent
(
person
-> {
person
.
setRemark
(
person
.
getRemark
() +
"
\n
更新更新更新更新更新"
);
Person
save
=
repo
.
save
(
person
);
log
.
info
(
"【save】= {}"
,
save
);
});
}
/**
* ???除
*/
@
Test
public
void
delete
() {
// 主??除
repo
.
deleteById
(
1L
);
// ?象?除
repo
.
findById
(
2L
).
ifPresent
(
person
->
repo
.
delete
(
person
));
// 批量?除
repo
.
deleteAll
(
repo
.
findAll
());
}
/**
* ??普通??,按生日倒序
*/
@
Test
public
void
select
() {
repo
.
findAll
(
Sort
.
by
(
Sort
.
Direction
.
DESC
,
"birthday"
))
.
forEach
(
person
->
log
.
info
(
"{} 生日: {}"
,
person
.
getName
(),
DateUtil
.
formatDateTime
(
person
.
getBirthday
())));
}
/**
* 自定???,根据年?范???
*/
@
Test
public
void
customSelectRangeOfAge
() {
repo
.
findByAgeBetween
(
18
,
19
).
forEach
(
person
->
log
.
info
(
"{} 年?: {}"
,
person
.
getName
(),
person
.
getAge
()));
}
/**
* 高???
*/
@
Test
public
void
advanceSelect
() {
// QueryBuilders 提供了?多??方法,可以??大部分???件的封?
MatchQueryBuilder
queryBuilder
=
QueryBuilders
.
matchQuery
(
"name"
,
"??"
);
log
.
info
(
"【queryBuilder】= {}"
,
queryBuilder
.
toString
());
repo
.
search
(
queryBuilder
).
forEach
(
person
->
log
.
info
(
"【person】= {}"
,
person
));
}
/**
* 自定?高???
*/
@
Test
public
void
customAdvanceSelect
() {
// ?造???件
NativeSearchQueryBuilder
queryBuilder
=
new
NativeSearchQueryBuilder
();
// 添加基本的分??件
queryBuilder
.
withQuery
(
QueryBuilders
.
matchQuery
(
"remark"
,
"??"
));
// 排序?件
queryBuilder
.
withSort
(
SortBuilders
.
fieldSort
(
"age"
).
order
(
SortOrder
.
DESC
));
// 分??件
queryBuilder
.
withPageable
(
PageRequest
.
of
(
0
,
2
));
Page
<
Person
>
people
=
repo
.
search
(
queryBuilder
.
build
());
log
.
info
(
"【people】??? = {}"
,
people
.
getTotalElements
());
log
.
info
(
"【people】??? = {}"
,
people
.
getTotalPages
());
people
.
forEach
(
person
->
log
.
info
(
"【person】= {},年? = {}"
,
person
.
getName
(),
person
.
getAge
()));
}
/**
* ??聚合,??平均年?
*/
@
Test
public
void
agg
() {
// ?造???件
NativeSearchQueryBuilder
queryBuilder
=
new
NativeSearchQueryBuilder
();
// 不??任何?果
queryBuilder
.
withSourceFilter
(
new
FetchSourceFilter
(
new
String
[]{
""
},
null
));
// 平均年?
queryBuilder
.
addAggregation
(
AggregationBuilders
.
avg
(
"avg"
).
field
(
"age"
));
log
.
info
(
"【queryBuilder】= {}"
,
JSONUtil
.
toJsonStr
(
queryBuilder
.
build
()));
AggregatedPage
<
Person
>
people
= (
AggregatedPage
<
Person
>)
repo
.
search
(
queryBuilder
.
build
());
double
avgAge
= ((
InternalAvg
)
people
.
getAggregation
(
"avg"
)).
getValue
();
log
.
info
(
"【avgAge】= {}"
,
avgAge
);
}
/**
* ??高?聚合??,每??家的人有??,每??家的平均年?是多少
*/
@
Test
public
void
advanceAgg
() {
// ?造???件
NativeSearchQueryBuilder
queryBuilder
=
new
NativeSearchQueryBuilder
();
// 不??任何?果
queryBuilder
.
withSourceFilter
(
new
FetchSourceFilter
(
new
String
[]{
""
},
null
));
// 1. 添加一?新的聚合,聚合?型?terms,聚合名??country,聚合字段?age
queryBuilder
.
addAggregation
(
AggregationBuilders
.
terms
(
"country"
).
field
(
"country"
)
// 2. 在?家聚合桶??行嵌套聚合,求平均年?
.
subAggregation
(
AggregationBuilders
.
avg
(
"avg"
).
field
(
"age"
)));
log
.
info
(
"【queryBuilder】= {}"
,
JSONUtil
.
toJsonStr
(
queryBuilder
.
build
()));
// 3. ??
AggregatedPage
<
Person
>
people
= (
AggregatedPage
<
Person
>)
repo
.
search
(
queryBuilder
.
build
());
// 4. 解析
// 4.1. ??果中取出名? country 的那?聚合,因?是利用String?型字段??行的term聚合,所以?果要强??StringTerm?型
StringTerms
country
= (
StringTerms
)
people
.
getAggregation
(
"country"
);
// 4.2. ?取桶
List
<
StringTerms
.
Bucket
>
buckets
=
country
.
getBuckets
();
for
(
StringTerms
.
Bucket
bucket
:
buckets
) {
// 4.3. ?取桶中的key,??家名? 4.4. ?取桶中的文??量
log
.
info
(
"{} ?共有 {} 人"
,
bucket
.
getKeyAsString
(),
bucket
.
getDocCount
());
// 4.5. ?取子聚合?果:
InternalAvg
avg
= (
InternalAvg
)
bucket
.
getAggregations
().
asMap
().
get
(
"avg"
);
log
.
info
(
"平均年?:{}"
,
avg
);
}
}
}
- ElasticSearch 官方文?:
https://www.elastic.co/guide/en/elasticsearch/reference/6.x/getting-started.html
- spring-data-elasticsearch 官方文?:
https://docs.spring.io/spring-data/elasticsearch/docs/3.1.2.RELEASE/reference/html/