- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Spring Boot集成ElasticSearch实现搜索引擎的示例由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
elastic search是一个开源的,分布式,实时搜索和分析引擎。spring boot为elasticsearch及spring data elasticsearch提供的基于它的抽象提供了基本的配置。spring boot提供了一个用于聚集依赖的spring-boot-starter-data-elasticsearch 'starterpom'.
elasticsearch作为搜索引擎,我们需要解决2大问题:
1, 如何将被搜索的数据在es上创建反向索引 2, java代码如何与es交互 。
其中第一个大问题又分为两个小问题 。
1.1,如何初始化已有的数据 1.2,如何同步增量数据 。
第二个大问题也有两种集成方式 。
2.1 spring data 9300端口集成 2.2 restful api 9200端口集成 。
本篇先解决第二大问题.
第一种方式,利用restapi方式,也叫jest方式:
示例代码:https://github.com/yejingtao/forblog/tree/master/demo-jest-elasticsearch 。
pom.xml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
<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>
<groupid>yejingtao.demo.springcloud</groupid>
<artifactid>demo-jest-elasticsearch</artifactid>
<version>
0.0
.
1
-snapshot</version>
<packaging>jar</packaging>
<name>demo-jest-elasticsearch</name>
<url>http:
//maven.apache.org</url>
<properties>
<project.build.sourceencoding>utf-
8
</project.build.sourceencoding>
</properties>
<parent>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-parent</artifactid>
<version>
1.5
.
6
.release</version>
</parent>
<dependencies>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-web</artifactid>
</dependency>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-data-elasticsearch</artifactid>
</dependency>
<dependency>
<groupid>io.searchbox</groupid>
<artifactid>jest</artifactid>
</dependency>
<dependency>
<groupid>net.java.dev.jna</groupid>
<artifactid>jna</artifactid>
</dependency>
</dependencies>
</project>
|
application.yml
1
2
3
4
5
6
7
8
9
|
server:
port:
7081
spring:
elasticsearch:
jest:
uris:
- http:
//192.168.226.133:9200
read-timeout:
5000
|
注意这里是9200端口 。
主程序:最简单的spring boot启动程序:
1
2
3
4
5
6
7
|
@springbootapplication
public
class
esapplication {
public
static
void
main(string[] args) {
springapplication.run(esapplication.
class
);
}
}
|
定义好es中的实体类和对es操作的接口:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
public
class
entity
implements
serializable{
private
static
final
long
serialversionuid = -763638353551774166l;
public
static
final
string index_name =
"index_entity"
;
public
static
final
string type =
"tstype"
;
private
long
id;
private
string name;
public
entity() {
super
();
}
public
entity(
long
id, string name) {
this
.id = id;
this
.name = name;
}
public
long
getid() {
return
id;
}
public
void
setid(
long
id) {
this
.id = id;
}
public
string getname() {
return
name;
}
public
void
setname(string name) {
this
.name = name;
}
}
|
1
2
3
4
5
6
7
8
|
public
interface
cityesservice {
void
saveentity(entity entity);
void
saveentity(list<entity> entitylist);
list<entity> searchentity(string searchcontent);
}
|
接口实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
@service
public
class
cityesserviceimpl
implements
cityesservice{
private
static
final
logger logger = loggerfactory.getlogger(cityesserviceimpl.
class
);
@autowired
private
jestclient jestclient;
@override
public
void
saveentity(entity entity) {
index index =
new
index.builder(entity).index(entity.index_name).type(entity.type).build();
try
{
jestclient.execute(index);
logger.info(
"es 插入完成"
);
}
catch
(ioexception e) {
e.printstacktrace();
logger.error(e.getmessage());
}
}
/**
* 批量保存内容到es
*/
@override
public
void
saveentity(list<entity> entitylist) {
bulk.builder bulk =
new
bulk.builder();
for
(entity entity : entitylist) {
index index =
new
index.builder(entity).index(entity.index_name).type(entity.type).build();
bulk.addaction(index);
}
try
{
jestclient.execute(bulk.build());
logger.info(
"es 插入完成"
);
}
catch
(ioexception e) {
e.printstacktrace();
logger.error(e.getmessage());
}
}
/**
* 在es中搜索内容
*/
@override
public
list<entity> searchentity(string searchcontent){
searchsourcebuilder searchsourcebuilder =
new
searchsourcebuilder();
//searchsourcebuilder.query(querybuilders.querystringquery(searchcontent));
//searchsourcebuilder.field("name");
searchsourcebuilder.query(querybuilders.matchquery(
"name"
,searchcontent));
search search =
new
search.builder(searchsourcebuilder.tostring())
.addindex(entity.index_name).addtype(entity.type).build();
try
{
jestresult result = jestclient.execute(search);
return
result.getsourceasobjectlist(entity.
class
);
}
catch
(ioexception e) {
logger.error(e.getmessage());
e.printstacktrace();
}
return
null
;
}
}
|
这里插入数据的方式给了两种,一种是单次api直接插入,一种是利用es的bulk批量插入.
做一个controller方面我们测试:
启动后在浏览器中请求http://localhost:7081/entitycontroller/search?name=%e4%ba%ba%e6%89%8b%e4%ba%95 。
得到结果:
这里只返回了9条记录,而理论上es默认的size是10,应该不是分页的问题,而是只能检索出9条匹配记录,用kibana连上相同的搜索确认下:
这里用的是standard分词方式,将每个中文都作为了一个term,凡是包含“人”“手”“井”的都被搜索了出来,只是评分不同,如果想支持只能中文索引需要依赖ik插件 。
ok,restful方式对elasticsearch的检索已经搞定了,更多的扩展可以慢慢研究下querybuilders里的源码和批注.
第二种方式,利用spring data客户端方式:
事先说明此方式有个弊端,让我掉了坑里好久才爬上来,spring data elasticsearch必须与elasticsearch版本相匹配,否则在对接时es端会报版本不匹配错误,例如我es是5.6.1版本,spring boot是1.5.6版本,错误如下:
为解决这个问题我查找了一些资料,spring data与elasticsearch版本对应关系如下:
。
spring data elasticsearch 。 |
elasticsearch 。 |
3.0.0.rc2 。 |
5.5.0 。 |
3.0.0.m4 。 |
5.4.0 。 |
2.0.4.release 。 |
2.4.0 。 |
2.0.0.release 。 |
2.2.0 。 |
1.4.0.m1 。 |
1.7.3 。 |
1.3.0.release 。 |
1.5.2 。 |
1.2.0.release 。 |
1.4.4 。 |
1.1.0.release 。 |
1.3.2 。 |
1.0.0.release 。 |
1.1.1 。 |
。
而我用的spring boot 1.5.6版本对应的spring data elasticsearch是2.1.6版本,不支持5.x的es,所以报错。到本博文撰写为止,spring boot的release版本最新的是1.5.8,对应的spring data elasticsearch是2.1.8,仍不支持5.x的es,所以如果一定要使用java客户端方式集成es只能放弃spring boot直接使用spring data和spring mvc,或者降低es的版本使之与spring boot匹配.
示例代码:https://github.com/yejingtao/forblog/tree/master/demo-data-elasticsearch 。
pom.xml依赖:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
<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>
<groupid>yejingtao.demo.springcloud</groupid>
<artifactid>demo-data-elasticsearch</artifactid>
<version>
0.0
.
1
-snapshot</version>
<packaging>jar</packaging>
<name>demo-data-elasticsearch</name>
<url>http:
//maven.apache.org</url>
<properties>
<project.build.sourceencoding>utf-
8
</project.build.sourceencoding>
</properties>
<parent>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-parent</artifactid>
<version>
1.5
.
8
.release</version>
</parent>
<dependencies>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-web</artifactid>
</dependency>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-data-elasticsearch</artifactid>
</dependency>
</dependencies>
</project>
|
不再引用jest.
application.yml
1
2
3
4
5
6
7
8
9
10
|
server:
port:
7081
spring:
data:
elasticsearch:
cluster-nodes:
192.168
.
226.133
:
9300
cluster-name: my-es
repositories:
enabled:
true
|
注意这里是9300端口 。
controller、主程序、service接口同jest项目不变,不再罗列 。
实体类稍作变化,指定es中的index和type:
1
|
@document
(indexname=
"index_entity"
, type=
"tstype"
)
|
多一个repository接口,无需实现类,spring data标准用法:
1
2
3
4
5
6
7
8
|
/**
* entity es操作类
* @author yejingtao
*
*/
public
interface
entityrepository
extends
elasticsearchrepository<entity,
long
>{
}
|
service实现类与jest的天壤之别了,从语法上可以看出更像是对数据库层的操作:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
@service
public
class
cityesserviceimpl
implements
cityesservice{
private
static
final
logger logger = loggerfactory.getlogger(cityesserviceimpl.
class
);
int
page_size =
15
;
//默认分页大小
int
page_number =
0
;
//默认当前分页
string score_mode_sum =
"sum"
;
//权重分求和模式
float
min_score =
10
.0f;
//由于无相关性的分值默认为1, 设置权重分最小值为10
@autowired
entityrepository entityrepository;
/**
* 保存内容到es
*/
@override
public
long
saveentity(entity entity) {
entity entityresult = entityrepository.save(entity);
return
entityresult.getid();
}
/**
* 在es中搜索内容
*/
@override
public
list<entity> searchentity(
int
pagenumber,
int
pagesize, string searchcontent){
if
(pagesize==
0
) {
pagesize = page_size;
}
if
(pagenumber<
0
) {
pagenumber = page_number;
}
searchquery searchquery = getentitysearchquery(pagenumber,pagesize,searchcontent);
logger.info(
"\n searchcity: searchcontent ["
+ searchcontent +
"] \n dsl = \n "
+ searchquery.getquery().tostring());
page<entity> citypage = entityrepository.search(searchquery);
return
citypage.getcontent();
}
/**
* 组装搜索query对象
* @param pagenumber
* @param pagesize
* @param searchcontent
* @return
*/
private
searchquery getentitysearchquery(
int
pagenumber,
int
pagesize, string searchcontent) {
functionscorequerybuilder functionscorequerybuilder = querybuilders.functionscorequery()
.add(querybuilders.matchphrasequery(
"name"
, searchcontent),
scorefunctionbuilders.weightfactorfunction(
1000
))
//.add(querybuilders.matchphrasequery("other", searchcontent),
//scorefunctionbuilders.weightfactorfunction(1000))
.scoremode(score_mode_sum).setminscore(min_score);
//设置分页,否则只能按照es默认的分页给
pageable pageable =
new
pagerequest(pagenumber, pagesize);
return
new
nativesearchquerybuilder().withpageable(pageable).withquery(functionscorequerybuilder).build();
}
}
|
测试方式同jest.
这两种方式,从设计上来讲属于两种思路,spring data的思路就是将elasticsearch当自家的数据仓库来管理,直接通过java客户端代码操作es;jest的思路是将elasticsearch当为独立的服务端,自己作为客户端用兼容性最强的restful格式来与之交互。 个人比较倾向于jest方式,第一兼容性好,不需要考虑版本的问题。第二,从elasticsearch本身的设计上来分析,9200是对外服务端口,9300是内部管理和集群通信端口,请求9200获取搜索服务更符合es的设计初衷,不会影响集群内部的通信。 以上比较分析仅代表个人观点,欢迎大神么交流批评。希望对大家的学习有所帮助,也希望大家多多支持我.
原文链接:http://blog.csdn.net/yejingtao703/article/details/78414874 。
最后此篇关于Spring Boot集成ElasticSearch实现搜索引擎的示例的文章就讲到这里了,如果你想了解更多关于Spring Boot集成ElasticSearch实现搜索引擎的示例的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
背景: 我最近一直在使用 JPA,我为相当大的关系数据库项目生成持久层的轻松程度给我留下了深刻的印象。 我们公司使用大量非 SQL 数据库,特别是面向列的数据库。我对可能对这些数据库使用 JPA 有一
我已经在我的 maven pom 中添加了这些构建配置,因为我希望将 Apache Solr 依赖项与 Jar 捆绑在一起。否则我得到了 SolarServerException: ClassNotF
interface ITurtle { void Fight(); void EatPizza(); } interface ILeonardo : ITurtle {
我希望可用于 Java 的对象/关系映射 (ORM) 工具之一能够满足这些要求: 使用 JPA 或 native SQL 查询获取大量行并将其作为实体对象返回。 允许在行(实体)中进行迭代,并在对当前
好像没有,因为我有实现From for 的代码, 我可以转换 A到 B与 .into() , 但同样的事情不适用于 Vec .into()一个Vec . 要么我搞砸了阻止实现派生的事情,要么这不应该发
在 C# 中,如果 A 实现 IX 并且 B 继承自 A ,是否必然遵循 B 实现 IX?如果是,是因为 LSP 吗?之间有什么区别吗: 1. Interface IX; Class A : IX;
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我正在阅读标准haskell库的(^)的实现代码: (^) :: (Num a, Integral b) => a -> b -> a x0 ^ y0 | y0 a -> b ->a expo x0
我将把国际象棋游戏表示为 C++ 结构。我认为,最好的选择是树结构(因为在每个深度我们都有几个可能的移动)。 这是一个好的方法吗? struct TreeElement{ SomeMoveType
我正在为用户名数据库实现字符串匹配算法。我的方法采用现有的用户名数据库和用户想要的新用户名,然后检查用户名是否已被占用。如果采用该方法,则该方法应该返回带有数据库中未采用的数字的用户名。 例子: “贾
我正在尝试实现 Breadth-first search algorithm , 为了找到两个顶点之间的最短距离。我开发了一个 Queue 对象来保存和检索对象,并且我有一个二维数组来保存两个给定顶点
我目前正在 ika 中开发我的 Python 游戏,它使用 python 2.5 我决定为 AI 使用 A* 寻路。然而,我发现它对我的需要来说太慢了(3-4 个敌人可能会落后于游戏,但我想供应 4-
我正在寻找 Kademlia 的开源实现C/C++ 中的分布式哈希表。它必须是轻量级和跨平台的(win/linux/mac)。 它必须能够将信息发布到 DHT 并检索它。 最佳答案 OpenDHT是
我在一本书中读到这一行:-“当我们要求 C++ 实现运行程序时,它会通过调用此函数来实现。” 而且我想知道“C++ 实现”是什么意思或具体是什么。帮忙!? 最佳答案 “C++ 实现”是指编译器加上链接
我正在尝试使用分支定界的 C++ 实现这个背包问题。此网站上有一个 Java 版本:Implementing branch and bound for knapsack 我试图让我的 C++ 版本打印
在很多情况下,我需要在 C# 中访问合适的哈希算法,从重写 GetHashCode 到对数据执行快速比较/查找。 我发现 FNV 哈希是一种非常简单/好/快速的哈希算法。但是,我从未见过 C# 实现的
目录 LRU缓存替换策略 核心思想 不适用场景 算法基本实现 算法优化
1. 绪论 在前面文章中提到 空间直角坐标系相互转换 ,测绘坐标转换时,一般涉及到的情况是:两个直角坐标系的小角度转换。这个就是我们经常在测绘数据处理中,WGS-84坐标系、54北京坐标系
在软件开发过程中,有时候我们需要定时地检查数据库中的数据,并在发现新增数据时触发一个动作。为了实现这个需求,我们在 .Net 7 下进行一次简单的演示. PeriodicTimer .
二分查找 二分查找算法,说白了就是在有序的数组里面给予一个存在数组里面的值key,然后将其先和数组中间的比较,如果key大于中间值,进行下一次mid后面的比较,直到找到相等的,就可以得到它的位置。
我是一名优秀的程序员,十分优秀!