Elasticsearch
一. 倒排索引和正排索引
正向索引在数据库领域用的比较多,它是将全文进行分词,用户查询的时候就到所有的分词中去匹配,如果有匹配到分词,最终该文档就出现结果集中。
倒排索引在搜索引擎领域用的比较多,它也会先进行分词,接着将分词与文档进行映射,分词就构成了一个词典,当用户查询的时候,首先到词典中查找对应的分词,然后将对应的文档获取到。 
二. ELK
Elasticsearch是真个elastic核心产品, 我们搜索都是该软件来实现的。
Logstash是一个数据输入、过滤、输出的管道,负责将不同来源数据过滤处理之后导入到Elasticsearch.
Kibana是一个操作 Elasticsearch的可视化界面,包括一些数据的统计模型。
三. Logstash的数导入
一, 将提供的数据集中 movies.csv 拷贝到 logstash的家目录下。
二,将配置文件拷贝到 LOGSTASH_HOME/config 目录下。
三, 依据情况修改 logstash.conf 配置文件中的路径。
三,导入数据,首先进到 LOGSTASH_HOME/bin, 打开dos命令行,执行如下的命令
# 具体执行的时候,将 LOGSTASH_HOME 缓存具体的Logstash的家目录
logstash -f LOGSTASH_HOME/config/logstash.conf
四. 名词
索引,类似于RDBMS中数据库的概念,在ES中有三层含义:1. 文档的集合;2. 倒排索引;3.XXX
type,类似于数据库中表的概念,在ES7以下的版本中,是有type来区分不同的数据集;但是ES7之后,统一都叫做 _doc
文档,类似于数据库中记录的概念,数据的格式是一个JSON.
属性,就是文档中的字段的名字。
五. 基本的查询
查看所有的索引:GET _cat/indices
查看电影数据集的内容:GET movies/_search
查看电影数据集的数量:GET movies/_count
查看指定id的文档: GET movies/_doc/1
六. 基本的增删查改
添加,自动生成id
POST user/_doc
{
"firstname": "Jack",
"lastname": "Ma"
}
添加,指定id
POST user/_doc/2
{
"firstname": "Pony",
"lastname": "Ma"
}
删除
DELETE uesr/_doc/2
修改
POST user/_update/2
{
"doc": {
age:34
}
}
批量添加
POST users/_bulk
{"index": {}}
{"firstname": "Rod", "lastname": "Jhonson"}
{"index": {"_id": 2}}
{"firstname": "Douge", "lastname": "Lee"}
七. Request Body查询
Request Body的查询需要的记住的就四个:
- match
- multi_match
- range
- bool
- match_phrase (用的比较少)
查询电影中名字包含2012的所有电影
GET movies/_search
{
"query": {
"match": {
"title": "2012"
}
}
}
查询电影的在1992年到1993年上映的所有的电影
GET movies/_search
{
"query": {
"range": {
"year": {
"gte": 1992,
"lte": 1993
}
}
}
}
查询电影中包含有2012的所有的电影
GET movies/_search
{
"query": {
"multi_match": {
"fields": ["title", "year"],
"query": 2012
}
}
}
查询电影的名字中包含有 beautiful 或者 mind 的电影
GET movies/_search
{
"query": {
"match": {
"title": "beautiful mind"
}
}
}
查询电影的名字中包含有beautiful和mind所有的电影
GET movies/_search
{
"query": {
"match": {
"title": {
"query": "beautiful mind",
"operator": "and" // or
}
}
}
}
查询电影的名字中包含有 “beautiful mind” 短语的电影
GET movies/_search
{
"query": {
"match_phrase": {
"title": "beautiful mind"
}
}
}
查询电影的名字中包含有 mind 或者 beautiful 的所有的电影,按照上映的年份进行倒序排序
GET movies/_search
{
"query": {
"match": {
"title": "beautiful mind"
}
},
"sort": [
{
"year": {
"order": "desc"
}
}
]
}
查询所有的战争片,然后分页
GET movies/_search
{
"query": {
"match": {
"genre": "war"
}
},
"from": 0,
"size": 10
}
查询所有的战争片,并且是在2012年上映的,然后分页
GET movies/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"genre": "war"
}
},
{
mathc: {
"year": 2012
}
}
]
}
},
"from": 0,
"size": 10
}
八. 分词器
ES内置了很多的分词,例如: stop、standard, simple, whitespace… 但是他们只针对英文处理。
ES的分词处理是 analysis, 它是通过 analyzer 来实现,analyzer 对于分词的处理分为三个步骤:
- character filter 过滤html标签
- tokenizer 切词,将一句话或者一个词切成一个个小的子或者词
- token filter, 将token处理之后的结果进一步处理,例如,去停用词、转大小写、转拼音。
8.1 IK和pinyin分词的安装
IK是中文分词社区中用的最多的一个分词器。
IK分词器的安装:在 ES_HOME/plugins 目录下创名为 ik 的目录,然后将 zip 文件拷贝到目录下,然后即可。
IK分词器的安装:在 ES_HOME/plugins 目录下创名为 pinyin 的目录,然后将 zip 文件拷贝到目录下,然后即可。
8.1.1 配置词库
因为IK分词器团队不可能将很多我们业务词汇加入到官方词库中,所以会导致有些词被切割了,所以我们需要配置自己的词库。
第一步,在IK分词的解压目录的 config 目录下创建一个名为 custome 的文件夹
第二步,在文件夹下创建名为 my.dic , 将自己的业务词库加进去(一个词一行),保存格式为 UTF-8
第三步,配置自定义的词典,打开 config 目录下的 IKAnalyzer.cfg.xml ,将自定义的词典配置进去,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<entry key="ext_dict">customer/my.dic</entry>
<entry key="ext_stopwords"></entry>
</properties>
九. 案例
实现类似于电商和百度的搜索功能。
9.1 配置自定义分词器
PUT stars
{
"settings": {
"analysis": {
"analyzer": {
"my_star_analyzer": {
"char_filter": "html_strip",
"tokenizer": "keyword",
"filter": "star_name_filter"
}
},
"filter": {
"star_name_filter": {
"type":"pinyin",
"keep_separate_first_letter" : false,
"keep_full_pinyin" : false,
"keep_original" : true,
"lowercase" : true,
"keep_joined_full_pinyin": true,
"remove_duplicated_term" : true
}
}
}
}
}
9.2 测试
针对如上的自定义分词器进行测试, 测试是否通过(满足我们的业务需求)
GET stars/_analyze
{
"analyzer": "my_star_analyzer",
"text": ["刘德华"]
}
9.3 插入样本数据
插入样本数据的目的就是为了获取mapping
POST stars/_doc
{
"name": "刘德华"
}
9.4 获取mapping信息
获取mapping信息
GET starts
拷贝其mapping信息
9.5 定义mapping
将 9.4 节获取到的mapping, 结合9.1 节自定义的分词器,创建业务所需的mapping
PUT stars/_mapping
{
"properties" : {
"name" : {
"type" : "completion",
"analyzer": "my_star_analyzer",
"search_analyzer": "keyword"
}
}
}
9.6 写入数据
POST stars/_bulk
{"index": {"_id": 1}}
{"name": "李小璐"}
{"index": {"_id": 2}}
{"name": "柳岩"}
{"index": {"_id": 3}}
{"name": "刘德华"}
{"index": {"_id": 4}}
{"name": "蔡徐坤"}
9.7 测试
样本一:
GET stars/_search
{
"_source": "",
"suggest": {
"start_name_prefix_suggest": {
"prefix": "ldh,
"completion": {
"field": "name"
}
}
}
}
样本二:
GET stars/_search
{
"_source": "",
"suggest": {
"start_name_prefix_suggest": {
"prefix": "lixiao,
"completion": {
"field": "name"
}
}
}
}
十一. 面试问题
数据写入到ES的过程?
- character_filter
- tokenizer
- token filter
工作中你用在哪里?怎嘛用的?
- 搜索提示,类似京东、百度的搜索提示。
- 内容检索。
搜索提示怎么做?
- 先根据IK分词、和 pinyin 分词自定义自己的分词器,配置 character_filter , tokenizer,token filter这些信息。
- 设置mapping信息,将我们用于提示的属性的类型设置
completion , 以及分词器设置成我们自定义的分词器。 - 导入数据(Logstash), 程序导入。
- 代码实现,前端展示。
内容检索怎么做?
- 定义mapping信息,将其分词器设置成 ik_smart 分词器。
- 写入数据。
- 根据用户搜索提示的信息,选中对应的词条,然后使用
match 和 multi_match 进行匹配。 - 检索数据使用高亮展示。
你的数据是怎么同步?增量数据?
|