一 ElasticSearch简介
Elasticsearch是一个实时的分布式搜索和分析引擎。它可以帮助你用前所未有的速度去处理大规模数据。ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。
先看看下面这张图:
我们的ElasticSearch就是上图的站内搜索。下表是ElasticSearch与MySQL数据库逻辑结构概念的对比:
二 ElasticSearch的基本操作
2.1 安装
安装很简单,去https://www.elastic.co/downloads/past-releases/elasticsearch-5-6-8 中去下载,直接解压就Ok了。
取到解压后去bin目录下打开cmd,输入:elasticsearch就启动了。我们可以去浏览器中验证一下:
注意:java开发是默认端口9300,其余都是9200。
2.2 Restful风格操作
创建一个索引库——tensquare_elasticsearch:
在索引库中添加一个文档——article:
查询所有操作:
根据id修改操作:
如果把上面修改的id改为一个不存在的id,如改为1,则此操作就会变成新建一个id为1的操作:
其他操作比如模糊查询,删除什么的大家网上查一下就知道。还有大家要记住,我们查询的单位是此条,这个概念到后面的ik分词器会介绍。
三 head插件
如果都是通过rest请求的方式使用Elasticsearch,未免太过麻烦,而且也不够人性化。我们一般都会使用图形化界面来实现Elasticsearch的日常管理,最常用的就是Head插件
我们将head插件解压后,可以看到如下目录
这是一个典型的node.js开发的插件,其中package.json的文件相当于maven工程里面的pom.xml文件,用来定位jar包的,现在我们就要来下载这些jar包。
因为这是node.js开发的,所以我们首先要安装node.js
安装完后,我们可以用npm来下载这些jar包,但是npm的服务器在国外,使用npm速度会比较慢,所以我们需要下载cnpm(淘宝开源的),用cnpm来安装jar包。我们先通过以下命令安装cnpm:
npm install -g cnpm --registry=https://registry.npm.taobao.org
将grunt安装为全局命令 。Grunt是基于Node.js的项目构建工具(你进入package.json文件看下dependencies就知道了)。它可以自动运行你所设定的任务。具体安装命令如下(cnpm中没有grunt,所以只能用npm):
npm install ‐g grunt‐cli
然后我们再在解压的head文件中执行下面命令安装jar包就可以了(前面的命令在哪个目录执行都可以):
cnpm install
最后我们再head目录下输入以下命令启动head:
grunt server
打开浏览器输入localhost:9100就出现下面页面啦
但是我们现点击连接,右边显示未连接,说明现在head连接不上elasticsearch,这是为什么了?因为elasticsearch没有设置跨域!
我们再elasticsearch的config文件夹下的elasticsearch.yml文件中最后两行添加下面两行语句:
http.cors.enabled: true
http.cors.allow-origin: "*"
然后重启elasticsearch,再用head去连接就成功啦
至于具体操作大家就看讲义或者网上搜下资料吧。
四 IK分词器
elasticsearch里面默认的中文分词是将每个字看成一个词,比如“我是程序员”就会默认分词为“我”,“是”,“程”,“序”,“员”来查找,这样显然不符合要求所以我们需要安装中文分词器来解决这个问题。
IK分词是一款国人开发的相对简单的中文分词器。虽然开发者自2012年之后就不在维护了,但在工程应用中IK算是比较流行的一款!我们今天就介绍一下IK中文分词器的使用。
4.1 安装
下载地址:https://github.com/medcl/elasticsearch-analysis-ik/releases 下载5.6.8版。本课程配套资源也提供了elasticsearch-analysis-ik-5.6.8.zip
(1)先将其解压,将解压后的elasticsearch文件夹重命名文件夹为ik
(2)将ik文件夹拷贝到elasticsearch/plugins 目录下。
(3)重新启动,即可加载IK分词器
4.2 自定义词库
IK提供了两个分词算法ik_smart 和 ik_max_word。其中 ik_smart 为最少切分,ik_max_word为最细粒度划分
现在我们用最小切分来测试下“传智播客”,在地址栏输入:http://127.0.0.1:9200/_analyze?analyzer=ik_smart&pretty=true&text=传智播客
咦,为什么还是单个的词?这是因为分词库里面还没有存入这个词,所以我们现在把“传智播客”这个词添加到分词库中。
我们现在ik目录下的config文件夹中添加一个custom.dic文件,里面加上“传智播客”一词,然后把这个文件的编码改成UTF-8,然后再进入IKAnalyzer.cfg.xml添加custom.dic,如下:
最后重启elasticsearch后重新查询就会出现下面的内容了。
五 文章模块(搜索索引库)
首先还是导入jar包,编写配置文件,编写启动类
5.1 索引库搜索
搜索框输入一个词,一般都要匹配多个字符(如title、content)
Dao层
package com.tensquare.search.dao;
//jar包省略
public interface ArticleDao extends ElasticsearchRepository<Article, String > {
public Page<Article> findByTitleOrContentLike(String title , String content , Pageable pageable);
}
Service层
package com.tensquare.search.service;
//jar包省略
@Service
public class ArticleService {
@Autowired
private ArticleDao articleDao;
public Page<Article> findByKey(String key, int page, int size) {
Pageable pageable = PageRequest.of(page-1 , size);
return articleDao.findByTitleOrContentLike(key , key , pageable);
}
}
Controller层
package com.tensquare.search.controller;
//jar包省略
@RestController
@CrossOrigin
@RequestMapping("/article")
public class ArticleController {
@Autowired
private ArticleService articleService;
@RequestMapping(value = "/{key}/{page}/{size}" , method = RequestMethod.GET)
public Result findByKey(@PathVariable String key , @PathVariable int page , @PathVariable int size){
Page<Article> pageData = articleService.findByKey(key , page ,size);
return new Result(true , StatusCode.OK , "查询成功" , new PageResult<Article>(pageData.getTotalElements(), pageData.getContent()));
}
}
5.2 索引库增加(一般都在后台通过下节的logstach直接批量添加,这个只是个例子,大家随便看看就好)
Pojo层
package com.tensquare.search.pojo;
//jar包这里省略
@Document(indexName = "tensquare_article" , type = "article") //indexname:索引库的名称(这个必须已经创建) type:数据库中的表的名称
public class Article implements Serializable {
@Id
private String id;
//是否索引,就是看该域是否被搜索
//是否分词,就表示搜索的时候是整体匹配还是单词匹配
//是否存储,就是是否在页面上显示
@Field(index = true , analyzer = "ik_max_word" , searchAnalyzer = "ik_max_word")
private String title;
@Field(index = true , analyzer = "ik_max_word" , searchAnalyzer = "ik_max_word")
private String content;
private String state;// 审核状态
//getter、setter这里省略
}
Dao层
package com.tensquare.search.dao;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
public interface ArticleDao extends ElasticsearchRepository<Article, String > {
}
Service
package com.tensquare.search.service;
//jar包省略
@Service
public class ArticleService {
@Autowired
private ArticleDao articleDao;
@Autowired
private IdWorker idWorker;
public void save(Article article){
article.setId(idWorker.nextId()+"");
articleDao.save(article);
}
}
Controller
package com.tensquare.search.controller;
//jar包省略
@RestController
@CrossOrigin
@RequestMapping("/article")
public class ArticleController {
@Autowired
private ArticleService articleService;
@RequestMapping(method = RequestMethod.POST)
public Result save(@RequestBody Article article){
articleService.save(article);
return new Result (true , StatusCode.OK , "添加成功");
}
}
最后执行下,数据就添加到elasticsearch索引库里去了
六. elasticsearch与mysql数据同步
Logstash是一款轻量级的日志搜集处理框架,可以方便的把分散的、多样化的日志起来,并进行自定义的处理,然后传输到指定的位置,比如某个服务器或者文件。
和前面介绍的软件一样,logstash也是解压后就可以用了。我们进入bin目录下的cmd里面,输入下面
logstash -e 'input { stdin{}} output {stdout{}}'
其中stdin,表示输入流,指从键盘输入;stdout,表示输出流,指从显示器输出:(控制台输入字符,随后就有日志输出)
命令行参数:
-e 执行。即后面直接接执行语句,如上面例子。但有时候命令太多,在命令行里面不太好写,所以可用下面命令行:
--config 或 -f 配置文件,后跟参数类型可以是一个字符串的配置或全路径文件名或全路径路径(如:/etc/logstash.d/,logstash会自动读取/etc/logstash.d/目录下所有*.conf 的文本文件,然后在自己内存里拼接成一个完整的大配置文件再去执行)