网站首页 > 技术文章 正文
使用ElasticSearch快速搭建数据搜索服务
1. ElasticSearch?
ElasticSearch 是最近几年Java界少有的当红炸子鸡,在Github上有19663个STAR。ES这两年在各个领域都有极大的发展,目前看来基本上是无所不能,我想是因为它的工作是数据的存储和索引,而数据是一切程序的本质,是基石的基石。
最简单的一个用法是搭建数据搜索服务,由于DNA是Lucence系的,很容易做Scoring和Sorting,提供Reseful的数据接口。配合中文分词Analyzer,可以做中文的全文检索。天生是分布式的。
2. Spring Data ElasticSearch?
Spring Data ElasticSearch是Spring Data 针对ElasticSearch封装的一套框架,目前还是孵化性质,版本之间变动特别大,其中一部分原因是ElasticSearch也在飞速变化中,直接从V2.4跳跃到V5.0。
虽然S D ES经常整个package被@Deprecate掉,但我个人觉得还是非常适合用来阅读源代码深入学习的:
初始版本聚焦核心功能,内容分支少,容易掌握
变化过程中,也了解专业程序员的设计思路及其取舍
3. 搜索服务搭建
ElasticSearch做数据存储Store、索引Index和检索Query
Spring-Data-ElasticSearch来完成”灌数据“和”取数据“的工作。
4. ES安装方法
ES的安装方法非常简单,下载最新的Bin包,解压即可!!
4.1 安装中文分词插件
插件地址 https://github.com/medcl/elasticsearch-analysis-ik/
下载ES版本对应的IK插件版本,解压到ES的plugins目录下即可。
修改config目录下配置文件elasticsearch.yml如下所示:
index.analysis.analyzer.ik.type : "ik"
index.analysis.analyzer.default.type : "ik"
4.2 安装Head插件
Head是一款非常好用的ElasticSearch数据图形化管理插件,类似于Mysql的NaviCat,安装方式非常简单:
sudo elasticsearch/bin/plugin install mobz/elasticsearch-head
访问 localhost:9200/_plugin/head/
5. Spring Data ElasticSearch代码示例
通过注解@Document 和 @Filed,可以在ES中配置一个可索引的的对象。
在@Document注解中,indexName可以理解为传统关系数据库的DB Name, type可以理解为Table Name.
@Document(indexName = "db_name", type = "table_name")
public class Item {
private String id;
@Field(analyzer = "ik", searchAnalyzer = "ik", type = FieldType.String) private String name;}
Spring Data Repository风格的Dao实现:
@Repository
public interface ItemDao extends ElasticsearchRepository<Item, String> {}
实现索引和查询的简单代码示例:
@Service
public class ItemService {
@Autowired private ItemDao itemDao;
@Autowired private ElasticsearchTemplate et;
public void indexItem() {
Item item = new Item("id", "name");
// 配合注解,一句话实现索引 itemDao.save(item); }
public Page<Item> search(String word, int page, int pageSize) {
// ES原生的模糊查询API SDE中
CriteriaQuery.Contains的实现 QueryBuilder queryBuilder =
queryStringQuery(word).
field("name").
analyzeWildcard(true).
boost(2f); SearchQuery searchQuery = new
NativeSearchQueryBuilder(). withQuery(queryBuilder). withPageable(new PageRequest(page, pageSize)). withMinScore(0.01f). build();
return et.queryForPage(searchQuery, Item.class); }}
附录: Spring Data ElasticSearch 源码阅读笔记
基本上看到这里,使用上已经足够,下面这些是我当时读源码时的一些笔记,比较散乱,感兴趣的可以看看。
1. 源码目录结构
五个主要package,分别是
annotations:各种注解,主要用到的是@Document 和 @Field
client:NodeClient 和 TransportClinet,用后者,前者是个玩具
config:配置包,随便看看
core:核心包,Query和Index主要功能包,重点看
repository: spring data的repository接口包,主要是和ES交互,随便看看
2. Core 包
2.1 Query 接口
Query 有两个直接子接口: SeachQuery 和抽象类 AbstractQuery,且两者有个共同的实现类 NativeSearchQuery,这个类需要重点关注下。
SearchQuery里的Facet 被干掉了,暴露了Query和Filter的builder。同时暴露了HightlightFileds,ScriptFields,IndexBoost之类的细节。
抽象类AbstractQuery implements Query 接口. (没有一个方法是Abstract的,理论上已经完全实现Query接口)
StringQuery,AbstractQuery的一个子类,增加了一个属性,Source。打酱油的,可以忽略。
AbstractQuery的子类:CriteriaQuery,非常重要的一个类。封装一个Fluent API Style的Criteria,能做 where, and, or, is, contains, startsWith, endsWith, not, contains, expression …… 等各种常用操作。
2.1.2 Criteria类
标准Spring Data风格的Criteria查询基础类
构造函数管理的对象是Field(只有一个属性name),还会有个Arraylist的CriteriaChain,存储一系列的CriteriaEntry用来生成查询语句
OrCriteria用来处理“或”条件,继承自Criteria,区别是 override 了 ConjunctionOperator
Criteria的contains,startsWith,endsWith等方法, 参数不接受空格
not方法,是将negating参数置为true
Criteria还支持Location GeoBox Bounding Box 查询(厉害,经纬度的查询)
CriteriaEntry的实现原理是转换成原生的ElasticSearch Query Java API,转换介质是枚举变量
public enum OperationKey {
EQUALS, CONTAINS, STARTS_WITH, ENDS_WITH, EXPRESSION, BETWEEN, FUZZY, IN, NOT_IN, WITHIN, BBOX, NEAR, LESS, LESS_EQUAL, GREATER, GREATER_EQUAL;
}
boost 是干啥的? postive hit with given factor
filter是干啥的? 用在Geo Location(地理信息)的查询中
2.1.3 CriteriaQuery类
封装了Criteria,没啥好说的。
2.1.4 NativeSearchQuery
它封装了ES里的QueryBuilder和SortBuilder,因此可以将Spring Data风格的Query转换过ElasticSearch的原生Query API,想要实现高度定制化的查询,全靠这个类。Spring Data ES提供有配套Builder.
2.1.5 ElasticSearchTemplate
继承自ElasticsearchOperations接口,是标准的Spring Data风格封装。
2.1.5.1 ElasticsearchOperations
主要包含以下几个方面的功能
索引的 创建
Mapping的创建(对indexName(database)和 Type (table)的Mapping,目前不知道是干啥的)
获取IndexName的Setting (数据格式是一个map)
常规的QueryForObject, QueryForPage等操作
count, multiGet
update, index, delete
scan, scroll
几个特殊的Query:MoreLikeThisQuery,AliasQuery
2.1.5.2 EST的实现
封装了一个ES的Client, 能完成index,mapping,setting相关的request请求
2.1.5.3 queryForPage实现
创建Query和Filter两个QueryBuilder(ES的),其中Query用于普通字段的查询,Filter用于Geo Location数据的查询。
Query-QuerBuidler里是根据CriteriaEntry和前面列举的枚举变量OperationKey转换成ES原生的queryStringQuery,rangeQuery,fuzzyQuery,boolQuery等
然后用一个BoolQueryBudiler(ES原生)把第2步生成的全部Query串起来。
辅助设置一下参数,例如SourceFilter,Pageable(转换成ES原生的起始点选择),sort,minscore之类的。
2.1.5.4 Scan实现
可以用来完成超大数据量的Scan && Scroll
暂时用不到,但数据规模到一定规模时,应该有用。(观察下Jest里的实现)
3. 结论
结合Spring和注解,在POJO上利用Document和Filed注解,然后结合Repository风格的Dao,可以非常有效的创建索引。 (save方法,推荐这么使用)
一些简单的、常规的查询,推荐使用CriteriaQuery,配合EST
复杂的、自定义的、得分排序等等高阶查询,需要是用SearchQuery集成ES原生的各种TermQuery、RangeQuery等。(所以还是要认真学下ES的原生JAVA API)
猜你喜欢
- 2024-10-01 全面解析45种设计模式(Design pattern)和六大原则
- 2024-10-01 5分钟了解(什么是设计模式)(设计模式的意思)
- 2024-10-01 mongoHelper 0.3.9 发布,简化 CRUD操作
- 2024-10-01 JPA 的 Metamodel(jpa格式图片)
- 2024-10-01 设计模式简介(设计模式是干嘛的)
- 2024-10-01 SlideLive网站:如何实现个性化搜索
- 2024-10-01 JPA核心接口EntityManager之API功能详解(三)
- 2024-10-01 SpringORM最佳实践:SpringData架构与应用
- 2024-10-01 Spring Data JPA 自定义存储库(spring data jpa调用存储过程)
- 2024-10-01 Spring Data之JPA @Query注解(spring+jpa)
- 1517℃桌面软件开发新体验!用 Blazor Hybrid 打造简洁高效的视频处理工具
- 594℃Dify工具使用全场景:dify-sandbox沙盒的原理(源码篇·第2期)
- 521℃MySQL service启动脚本浅析(r12笔记第59天)
- 489℃服务器异常重启,导致mysql启动失败,问题解决过程记录
- 489℃启用MySQL查询缓存(mysql8.0查询缓存)
- 477℃「赵强老师」MySQL的闪回(赵强iso是哪个大学毕业的)
- 456℃mysql服务怎么启动和关闭?(mysql服务怎么启动和关闭)
- 454℃MySQL server PID file could not be found!失败
- 最近发表
-
- PS所有滤镜的说明(六)(ps滤镜详解)
- 5款小白也能用的在线图片编辑器!电商效率飙升就靠它!
- Java变量(java变量有什么作用)
- Java面试常见问题:Java注解(java中的面试题)
- Java编程入门第一课:HelloWorld(java编程从入门到实践)
- Java基础教程:Java继承概述(java里继承的概述)
- java基础之——访问修饰符(private/default/protected/public)
- 如何规划一个合理的JAVA项目工程结构
- 将机器指令翻译成 JavaScript -- 终极目标
- Web 服务器基准测试:Go vs. Node.js vs. Nim vs. Bun
- 标签列表
-
- cmd/c (90)
- c++中::是什么意思 (84)
- 标签用于 (71)
- 主键只能有一个吗 (77)
- c#console.writeline不显示 (95)
- pythoncase语句 (81)
- es6includes (73)
- windowsscripthost (67)
- apt-getinstall-y (86)
- node_modules怎么生成 (76)
- c++int转char (75)
- static函数和普通函数 (76)
- el-date-picker开始日期早于结束日期 (70)
- js判断是否是json字符串 (67)
- checkout-b (67)
- c语言min函数头文件 (68)
- asynccallback (71)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- eacces (67)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)