一. 安装elasticsearch
下载elasticsearch, 解压, 运行即可
二. 安装ES的图形化界面插件
.....略
三. elasticsearch的相关概念
Elasticsearch是面向文档(document oriented)的,这意味着它可以存储整个对象或文档(document)。然而它不仅仅是存储(store),还会索引(index)每个文档的内容使之可以被搜索。在Elasticsearch中,你可以对文档(而非成行成列的数据)进行索引、搜索、排序、过滤。Elasticsearch比较传统关系型数据库如下:
1
2
Relational DB -> Databases -> Tables -> Rows -> Columns Elasticsearch -> Indices -> Types -> Documents -> Fields
3.2 核心概念
3.2.1 索引 index
一个索引就是一个拥有几分相似特征的文档的集合。比如说,你可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单数据的索引。一个索引由一个名字来标识(必须全部是小写字母的),并且当我们要对对应于这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。在一个集群中,可以定义任意多的索引。
3.2.2. 类型 type
在一个索引中,你可以定义一种或多种类型。一个类型是你的索引的一个逻辑上的分类/分区,其语义完全由你来定。通常,会为具有一组共同字段的文档定义一个类型。比如说,我们假设你运营一个博客平台并且将你所有的数据存储到一个索引中。在这个索引中,你可以为用户数据定义一个类型,为博客数据定义另一个类型,当然,也可以为评论数据定义另一个类型。
3.2.3. 文档 document
一个文档是一个可被索引的基础信息单元。比如,你可以拥有某一个客户的文档,某一个产品的一个文档,当然,也可以拥有某个订单的一个文档。文档以JSON(Javascript Object Notation)格式来表示,而JSON是一个到处存在的互联网数据交互格式。
在一个index/type里面,你可以存储任意多的文档。注意,尽管一个文档,物理上存在于一个索引之中,文档必须被索引/赋予一个索引的type。
3.2.4. 字段Field
相当于是数据表的字段,对文档数据根据不同属性进行的分类标识
3.2.5. 映射 mapping
mapping是处理数据的方式和规则方面做一些限制,如某个字段的数据类型、默认值、分词器、是否被索引等等,这些都是映射里面可以设置的,其它就是处理es里面数据的一些使用规则设置也叫做映射,按着最优规则处理数据对性能提高很大,因此才需要建立映射,并且需要思考如何建立映射才能对性能更好。
4. Java操作ElasticSearch
4.1 搭建ElasticSearch操作环境
4.1.1 创建Maven工程
4.1.2 引入ElasticSearch坐标
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
<dependencies>
<dependency>
<groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>5.6.8</version> </dependency> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>transport</artifactId> <version>5.6.8</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-to-slf4j</artifactId> <version>2.9.1</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.24</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.21</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.12</version> </dependency> </dependencies>
4.2 操作ElasticSearch
4.2.1 新建索引+添加文档
使用创建索引+自动创建映射(Elasticsearch帮助我们自动建立映射,后续讲完分词器后,手动建立映射)
public class EsTest { @Test //创建索引+插入文档 public void fun01() throws Exception { //1.创建客户端连接对象,设置连接地址 TransportClient client = new PreBuiltTransportClient(Settings.EMPTY); client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300)); //2.创建文档数据 {id:1,title:"xxx",content:"xxxxxx"} /*XContentBuilder builder = XContentFactory.jsonBuilder().startObject() .field("id", 1) .field("title", "ElasticSearch是一个基于Lucene的搜索服务器") .field("content", "ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,
基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。") .endObject();*/ Map<String,Object> map = new HashMap<String, Object>(); map.put("id",1); map.put("title","ElasticSearch是一个基于Lucene的搜索服务器"); map.put("content","ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,
基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。"); //3.创建索引、创建文档类型、设置唯一主键,设置文档 client.prepareIndex("blog","article","1").setSource(map).get(); //4.释放资源 client.close(); } }
head插件查看信息:http://localhost:9100
4.2.2 查询全部 matchAllQuery()
@Test //查询所有的文档 public void fun02() throws Exception { //1.创建客户端连接对象,设置连接地址 PreBuiltTransportClient client = new PreBuiltTransportClient(Settings.EMPTY); client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"),9300)); //2.指定索引库和类型 SearchRequestBuilder searchRequestBuilder = client.prepareSearch("blog").setTypes("article"); //3.设置查询条件,进行查询 SearchResponse searchResponse = searchRequestBuilder.setQuery(QueryBuilders.matchAllQuery()).get(); //4.处理结果 SearchHits hits = searchResponse.getHits(); System.out.println("条数="+hits.totalHits); for (SearchHit hit : hits) { System.out.println("id="+hit.getId()); System.out.println("标题="+hit.getSource().get("title")); System.out.println("内容="+hit.getSource().get("content")); System.out.println("---------------"); } //5.关闭资源 client.close(); }
特点:
自动的分词 再搜索
4.2.3 字符串搜索StringQurey()
@Test //字符串查询 public void test3() throws Exception { //创建客户端访问对象 TransportClient client = new PreBuiltTransportClient(Settings.EMPTY).addTransportAddress( new InetSocketTransportAddress( InetAddress.getByName("127.0.0.1"), 9300)); //设置查询条件 SearchResponse searchResponse = client.prepareSearch("blog").setTypes("article") .setQuery(QueryBuilders.queryStringQuery("搜索").field("title")) // 默认在所有的字段上进行搜索,搜索“搜素”;如果添加.field("title"):表示只在title字段进行搜索 .get(); //处理结果 SearchHits hits = searchResponse.getHits(); //获得命中目标,即查询到了多少个对象 System.out.println("共查询"+hits.getTotalHits()+"条"); Iterator<SearchHit> ite = hits.iterator(); while(ite.hasNext()){ SearchHit searchHit = ite.next(); System.out.println(searchHit.getSourceAsString()); System.out.println(searchHit.getSource().get("title")); } //关闭资源 client.close(); }
查看结果能搜索出来结果。
4.2.4 词条查询termQuery()
什么是词条:
代码
@Test //词条查询 public void fun04() throws Exception { //1.创建客户端连接对象, 设置连接地址 PreBuiltTransportClient client = new PreBuiltTransportClient(Settings.EMPTY); client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300)); //2.指定索引库和内容 SearchRequestBuilder searchRequestBuilder = client.prepareSearch("blog").setTypes("article"); //3.设置查询添加进行查询 SearchResponse searchResponse = searchRequestBuilder.setQuery(QueryBuilders.termQuery("title","搜索")).get(); //4.处理结果 SearchHits hits = searchResponse.getHits(); System.out.println("条数="+hits.totalHits); for (SearchHit hit : hits) { System.out.println("id="+hit.getId()); System.out.println("title="+hit.getSource().get("title")); System.out.println("content="+hit.getSource().get("content")); } //5.释放资源 client.close(); }
4.2.5 模糊查询wildcardQuery()
@Test /** * 模糊查询 * *匹配任意字符 * ?匹配1个字符 */ public void fun05() throws Exception { //1.创建客户端连接对象, 设置连接地址 PreBuiltTransportClient client = new PreBuiltTransportClient(Settings.EMPTY); client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300)); //2.指定索引库和内容 SearchRequestBuilder searchRequestBuilder = client.prepareSearch("blog").setTypes("article"); //3.设置查询添加进行查询 SearchResponse searchResponse = searchRequestBuilder.setQuery(QueryBuilders.wildcardQuery("title","*搜索*")).get(); //4.处理结果 SearchHits hits = searchResponse.getHits(); System.out.println("条数="+hits.totalHits); for (SearchHit hit : hits) { System.out.println("id="+hit.getId()); System.out.println("title="+hit.getSource().get("title")); System.out.println("content="+hit.getSource().get("content")); } //5.释放资源 client.close(); }
4.2.6 小结
字符串查询 默认查询所有字段上的内容。字符串查询“搜索”时能搜索出结果。因为先进行分词成 一个个单词再进行查询,能查询到。
词条查询 查询指定字段上的内容。词条查询“搜索”时查询不结果。因为查询时 不分词 ,索引中没有“搜索”的词条,所以查询不到。
模糊查询(通配符查询)
使用 * 表示任意字符 可以占一个字符也可以不占。
使用 ? 表示任意字符 但是一定要占一个字符。
5 IK 分词器和ElasticSearch集成使用
5.1 上述查询存在问题分析
在进行词条查询时,我们搜索“搜索”却没有搜索到数据!
原因:默认是单字分词,默认的中文分词是将每个字看成一个词,这显然是不符合要求的,所以我们需要安装中文分词器来解决这个问题。解决方案:使用IK分词器
5.2 IK分词器
5.2.1 什么是IK分词器
IK分词是一款国人开发的相对简单的中文分词器。虽然开发者自2012年之后就不在维护了,但在工程应用中IK算是比较流行的一款!
5.2.2 IK分词器安装
下载地址:
https://github.com/medcl/elasticsearch-analysis-ik/releases
我们已经提供:
- 先将其解压,将解压后的elasticsearch文件夹重命名文件夹为ik
- 将ik文件夹拷贝到elasticsearch/plugins 目录下。
- 重新启动,即可加载IK分词器
5.2.3 IK分词器测试
IK提供了两个分词算法ik_smart 和 ik_max_word. 其中 ik_smart 为最少切分(智能切分),ik_max_word为最细粒度划分
- 第一种:最小切分
- 第二种:种最细切分
测试第一种:浏览器中输入:
http://127.0.0.1:9200/_analyze?analyzer=ik_smart&pretty=true&text=我是程序员
测试第二种:浏览器输入:
http://127.0.0.1:9200/_analyze?analyzer=ik_max_word&pretty=true&text=我是程序员
5.2.4 自定义词库
我们现在测试“传智播客”,浏览器的测试效果如下 http://127.0.0.1:9200/_analyze?analyzer=ik_smart&pretty=true&text=传智播客
{
"tokens" : [
{
"token" : "传", "start_offset" : 0, "end_offset" : 1, "type" : "CN_CHAR", "position" : 0 }, { "token" : "智", "start_offset" : 1, "end_offset" : 2, "type" : "CN_CHAR", "position" : 1 }, { "token" : "播", "start_offset" : 2, "end_offset" : 3, "type" : "CN_CHAR", "position" : 2 }, { "token" : "客", "start_offset" : 3, "end_offset" : 4, "type" : "CN_CHAR", "position" : 3 } ] }
默认的分词并没有识别“传智播客”是一个词。如果我们想让系统识别“传智播客”是一个词,需要编辑自定义词库 .
- 进入elasticsearch/plugins/ik/config目录
- 新建一个my.dic文件,编辑内容(以utf8无bom保存, 如果不行加一些换行)
传智播客
- 修改IKAnalyzer.cfg.xml(在ik/config目录下)
<properties>
<comment>IK Analyzer 扩展配置</comment> <!‐‐用户可以在这里配置自己的扩展字典 ‐‐> <entry key="ext_dict">my.dic</entry> <!‐‐用户可以在这里配置自己的扩展停止词字典‐‐> <entry key="ext_stopwords"></entry> </properties>
- 重新启动elasticsearch,通过浏览器测试分词效果