淘宝阿里京东腾讯等一线大厂都在用的搜索引擎技术,你确定不来看看?
Posted XiaoLin__Java
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了淘宝阿里京东腾讯等一线大厂都在用的搜索引擎技术,你确定不来看看?相关的知识,希望对你有一定的参考价值。
一、ElasticSearch简介
1.1、什么是全文检索
全文检索是计算机程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置。当用户查询时根据建立的索引查找,类似于通过字典的检索字表查字的过程。
检索: 索(建立索引) 检:(检索索引)
全文检索(Full-Text Retrieval(检索))以文本作为检索对象,找出含有指定词汇的文本。全面、准确和快速是衡量全文检索系统的关键指标。
全文检索的特点:
- 只处理文本。
- 不处理语义。
- 搜索时英文不区分大小写。
- 结果列表有相关度排序。
1.2、什么是ElasticSearch
ElasticSearch 简称ES ,是基于Apache Lucene构建的开源搜索引擎,是当前流行的企业级搜索引擎。Lucene本身就可以被认为迄今为止性能最好的一款开源搜索引擎工具包,但是lucene的API相对复杂,需要深厚的搜索理论。很难集成到实际的应用中去。但是ES是采用java语言编写,提供了简单易用的RestFul API,开发者可以使用其简单的RestFul API,开发相关的搜索功能,从而避免lucene的复杂性。
1.3、ElasticSearch 的诞生
多年前,一个叫做Shay Banon的刚结婚不久的失业开发者,由于妻子要去伦敦学习厨师,他便跟着也去了。在他找工作的过程中,为了给妻子构建一个食谱的搜索引擎,他开始构建一个早期版本的Lucene。
直接基于Lucene工作会比较困难,所以Shay开始抽象Lucene代码以便Java程序员可以在应用中添加搜索功能。他发布了他的第一个开源项目,叫做“Compass”。
后来Shay找到一份工作,这份工作处在高性能和内存数据网格的分布式环境中,因此高性能的、实时的、分布式的搜索引擎也是理所当然需要的。然后他决定重写Compass库使其成为一个独立的服务叫做Elasticsearch。
第一个公开版本出现在2010年2月,在那之后Elasticsearch已经成为Github上最受欢迎的项目之一,代码贡献者超过300人。一家主营Elasticsearch的公司就此成立,他们一边提供商业支持一边开发新功能,不过Elasticsearch将永远开源且对所有人可用。
Shay的妻子依旧等待着她的食谱搜索……
1.4、ElasticSearch应用场景
ES主要以轻量级JSON作为数据存储格式,这点与MongoDB有点类似,但它在读写性能上优于 MongoDB 。同时也支持地理位置查询 ,还方便地理位置和文本混合查询 。 以及在统计、日志类数据存储和分析、可视化这方面是引领者。国内外的使用场景为:
- 国外: Wikipedia(维基百科)使用ES提供全文搜索并高亮关键字、StackOverflow(IT问答网站)结合全文搜索与地理位置查询、Github使用Elasticsearch检索1300亿行的代码。
- 国内:百度(在云分析、网盟、预测、文库、钱包、风控等业务上都应用了ES,单集群每天导入30TB+数据, 总共每天60TB+)、新浪 、阿里巴巴、腾讯等公司均有对ES的使用。
二、ElasticSearch安装
2.1、环境准备
- centos7
- jdk(1.8以上)
- ElasticSearch6.8.0
2.2、下载ElasticSearch
我们可以从官网下载ElasticSearch
wget http://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.8.0.tar.gz
2.3、安装JDK
2.3.1、下载JDK
# 默认位置是 /usr/java/jdk1.8.0_171-amd64*/
rpm -ivh jdk-8u181-linux-x64.rpm
2.3.2、配置环境变量
vim /etc/profile
在这个配置文件的末尾加入:
export JAVA_HOME=/usr/java/jdk1.8.0_171-amd64
export PATH=$PATH:$JAVA_HOME/bin
2.3.3、重载系统配置
source /etc/profile
2.4、ElasticSearch安装(Linux)
2.4.1、添加新的用户并且赋予权限
# 在linux系统中创建新的组
groupadd es
# 创建新的用户xialin并将es用户放入es组中
useradd xiaolin -g es
# 修改es用户密码
passwd xiaolin
# 赋予权限(给xiaolin赋予/usr文件夹下所有权限)
chown -R xiaolin /usr
2.4.2、解压
tar -zxvf elasticsearch-6.4.1.tar.gz
2.4.3、了解目录结构
- bin 可执行的二进制文件的目录
- config 配置文件的目录
- lib 运行时依赖的库
- logs 运行时日志文件
- modules 运行时依赖的模块
- plugins 可以安装官方以及第三方插件
2.4.4、启动服务
进入bin目录中启动ES服务
./elasticsearch
2.4.5、测试
默认web服务端口9200,真正的java端口(tcp端口)9300,任何身份都可以访问
# (curl相当于模拟浏览器,检测es是否安装成功且默认不允许远程链接)
curl http://localhost:9200
2.4.6、开启远程连接
注意:ES服务默认启动是受保护的,只允许本地客户端连接,如果想要通过远程客户端访问,必须开启远程连接
我们只需要
三、ElasticSearch基本概念
3.1、接近实时(NRT Near Real Time )
Elasticsearch是一个接近实时的搜索平台。这意味着,从索引一个文档直到这个文档能够被搜索到有一个轻微的延迟(通常是1秒内)
3.2、索引
ElasticSearch操作流程
- 当ElasticSearch执行添加操作时,先将数据添加到索引中,然后根据指定好的分词器规则对text类型字段进行分词。
- 字段分词之后,会得到一系列词根,ElasticSearch将这些词根保存到一张倒排索引表中,这张表会建立词根与文档之间的关联关系。
- 当用户进行全文检索的时候,输入查询语句关键词语的时候,ElasticSearch会对这个关键词语进行分词,然后根据这些去匹配倒排索引表,如果这些分词与倒排索引表词根能够匹配,那么词根关联文档的id就是满足搜索条件的文档。
- ElasticSearch会将满足搜索的文档一个一个去查询,然后进行综合评分,排序后再返回。
一个索引就是一个拥有几分相似特征的文档的集合。比如说,你可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单数据的索引。一个索引由一个名字来标识(必须全部是小写字母的),并且当我们要对这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。索引类似于关系型数据库中Database 的概念。在一个集群中,如果你想,可以定义任意多的索引。
3.3、类型
在一个索引中,你可以定义一种或多种类型。一个类型是你的索引的一个逻辑上的分类/分区,其语义完全由你来定。通常,会为具有一组共同字段的文档定义一个类型。比如说,我们假设你运营一个博客平台并且将你所有的数 据存储到一个索引中。在这个索引中,你可以为用户数据定义一个类型,为博客数据定义另一个类型,当然,也可 以为评论数据定义另一个类型。类型类似于关系型数据库中Table的概念。 不同的版本对索引的要求也不同。
版本 | Type |
---|---|
5.x | 支持多种 type |
6.x | 只能有一种 type |
7.x | 默认不再支持自定义索引类型(默认类型为:_doc) |
3.4、映射
Mapping是ES中的一个很重要的内容,它类似于传统关系型数据中table的schema,用于定义一个索引(index)中的类型(type)的数据的结构。 在ES中,我们可以手动创建type(相当于table)和mapping(相关与schema),也可以采用默认创建方式。在默认配置下,ES可以根据插入的数据自动地创建type及其mapping。 mapping中主要包括字段名、字段数据类型和字段索引类型
3.5、文档
**一个文档是一个可被索引的基础信息单元,类似于表中的一条记录。**比如,你可以拥有某一个员工的文档,也可以拥有某个商品的一个文档。文档以采用了轻量级的数据交换格式JSON(javascript Object Notation)来表示。
3.6、分片
一个索引可以存储超出单个节点硬件限制的大量数据。比如,一个具有 10 亿文档数据的索引占据 1TB 的磁盘空间,而任一节点都可能没有这样大的磁盘空间。或者单个节点处理搜索请求,响应太慢。为了解决这个问题,Elasticsearch 提供了将索引划分成多份的能力,每一份就称之为分片。当你创建一个索引的时候,你可以指定你想要的分片的数量。每个分片本身也是一个功能完善并且独立的“索引”,这个“索引”可以被放置到集群中的任何节点上。
分片很重要,主要有两方面的原因:
- 允许你水平分割 / 扩展你的内容容量。
- 允许你在分片之上进行分布式的、并行的操作,进而提高性能/吞吐量。
至于一个分片怎样分布,它的文档怎样聚合和搜索请求,是完全由 Elasticsearch 管理的,对于作为用户的你来说,这些都是透明的,无需过分关心。
3.6.1、分片原理
传统的数据库每个字段存储单个值,但这对全文检索并不够。文本字段中的每个单词需要被搜索,对数据库意味着需要单个字段有索引多值的能力。最好的支持是一个字段多个值需求的数据结构是倒排索引。
Elasticsearch 使用一种称为倒排索引的结构,它适用于快速的全文搜索。
见其名,知其意,有倒排索引,肯定会对应有正向索引。正向索引(forward index),反向索引(inverted index)更熟悉的名字是倒排索引。
3.6.2、正排索引
所谓的正向索引,就是搜索引擎会将待搜索的文件都对应一个文件 ID,搜索时将这个ID 和搜索关键字进行对应,形成 K-V 对,然后对关键字进行统计计数。
但是互联网上收录在搜索引擎中的文档的数目是个天文数字,这样的索引结构根本无法满足实时返回排名结果的要求。于是倒排索引他来了!
3.6.3、倒排索引
倒排索引是把文件ID 对应到关键词的映射转换为关键词到文件ID 的映射,每个关键词都对应着一系列的文件,这些文件中都出现这个关键词。
一个倒排索引由文档中所有不重复词的列表构成,对于其中每个词,有一个包含它的文档列表。例如,假设我们有两个文档,每个文档的 content 域包含如下内容:
- The quick brown fox jumped over the lazy dog
- Quick brown foxes leap over lazy dogs in summer
为了创建倒排索引,我们首先将每个文档的 content 域拆分成单独的 词(我们称它为 词条或 tokens ),创建一个包含所有不重复词条的排序列表,然后列出每个词条出现在哪个文档。
现在,如果我们想搜索 quick
和brown
,我们只需要查找包含每个词条的文档.
两个文档都匹配,但是第一个文档比第二个匹配度更高。如果我们使用仅计算匹配词条数量的简单相似性算法,那么我们可以说,对于我们查询的相关性来讲,第一个文档比第二个文档更佳。
3.7、副本
在一个网络 / 云的环境里,失败随时都可能发生,在某个分片/节点不知怎么的就处于离线状态,或者由于任何原因消失了,这种情况下,有一个故障转移机制是非常有用并且是强烈推荐的。为此目的,Elasticsearch 允许你创建分片的一份或多份拷贝,这些拷贝叫做复制分片(副本)。
复制分片之所以重要,有两个主要原因:
- 在分片/节点失败的情况下,提供了高可用性。因为这个原因,注意到复制分片从不与原/主要(original/primary)分片置于同一节点上是非常重要的。
- 扩展你的搜索量/吞吐量,因为搜索可以在所有的副本上并行运行。
四、Kibana
4.1、概述
Kibana是一个针对Elasticsearch的开源分析及可视化平台,使用Kibana可以查询、查看并与存储在ES索引的数据进行交互操作,使用Kibana能执行高级的数据分析,并能以图表、表格和地图的形式查看数据。Kibana与Elasticsearch版本保持严格一致。
4.2、下载安装Kibana
下载Kibana
安装下载Kibana
rpm -ivh kibana-6.2.4-x86_64.rpm
查找kibana的安装位置
find / -name kibana
编辑kibana配置文件
vim /etc/kibana/kibana.yml
修改配置
#ES服务器主机地址
server.host: "192.168.202.200"
#ES服务器地址
elasticsearch.hosts: ["http://192.168.202.200:9200"]
启动kibana
# 启动kibana
systemctl start kibana
# 停止kibana
systemctl stop kibana
# 查看1kibana状态
systemctl status kibana
访问测试
kibana默认端口为5601 使用主机:端口直接访问即可 。
五、Kibana的基本操作
5.1、索引的基本操作
5.1.1、创建索引
put /student/
5.1.2、删除索引
delete /student
5.1.3、删除所有索引
delete /*
5.1.4、查看所有索引信息
get /_cat/indices?v
5.2、类型的基本操作
5.2.1、创建类型
创建/shop索引并创建(product)类型,这种方式创建类型要求索引不能存在。
PUT /shop
{
"mappings": {
"product": {
"properties": {
"title": { "type": "text" },
"name": { "type": "text" },
"age": { "type": "integer" },
"created": {
"type": "date"
}
}
}
}
}
5.2.1、查看类型
# 语法格式
get /索引名/_mapping/类型名
# 示范
get /shop/_mapping/product
5.3、文档的基本操作
5.3.1、添加文档
# /索引/类型/id
PUT /school/student/1
{
"name":"xiaolin",
"age":23,
"bir":"2012-12-12",
"content":"这是一个好一点的学生"
}
5.3.2、查询文档
GET /school/student/1
# 以下是返回结果
{
"_index": "school",
"_type": "student",
"_id": "1",
"_version": 1,
"found": true,
"_source": {
"name": "xiaolin",
"age": 23,
"bir": "2012-12-12",
"content": "这是一个好一点的学生"
}
}
5.3.3、删除文档
DELETE /school/student/1
# 以下是返回结果
{
"_index": "school",
"_type": "student",
"_id": "1",
"_version": 2,
"result": "deleted", #删除成功
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 1,
"_primary_term": 1
}
5.3.4、更新文档
5.3.4.1、第一种方式(更新原有的数据)
POST /school/student/1/_update
{
"doc":{
"name":"xiaohei"
}
}
5.3.4.2、第二种方式(添加新数据)
POST /school/student/1/_update
{
"doc":{
"name":"xiaohei",
"age":11,
"dpet":"hello world"
}
}
六、Query高级检索
6.1、检索方式
ES官方提供了两中检索方式:
- 一种是通过 URL 参数进行搜索,类似:GET /索引/类型/_search?参数
- 一种是通过 DSL(Domain Specified Language) 进行搜索,类似:GET /索引/类型/_search {}
官方更推荐使用第二种方式,第二种方式是基于传递JSON作为请求体(request body)格式与ES进行交互,这种方式更强大,更简洁
6.2、准备数据
# 删除索引
DELETE /ems
# 创建索引并指定类型
PUT /ems
{
"mappings":{
"emp":{
"properties":{
"name":{
"type":"text"
},
"age":{
"type":"integer"
},
"bir":{
"type":"date"
},
"content":{
"type":"text"
},
"address":{
"type":"keyword"
}
}
}
}
}
# 插入测试数据
PUT /ems/emp/_bulk
{"index":{}}
{"name":"小黑","age":23,"bir":"2012-12-12","content":"为开发团队选择一款优秀的MVC框架是件难事儿,在众多可行的方案中决择需要很高的经验和水平","address":"北京"}
{"index":{}}
{"name":"王小黑","age":24,"bir":"2012-12-12","content":"Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式","address":"上海"}
{"index":{}}
{"name":"张小五","age":8,"bir":"2012-12-12","content":"Spring Cloud 作为Java 语言的微服务框架,它依赖于Spring Boot,有快速开发、持续交付和容易部署等特点。Spring Cloud 的组件非常多,涉及微服务的方方面面,井在开源社区Spring 和Netflix 、Pivotal 两大公司的推动下越来越完善","address":"无锡"}
{"index":{}}
{"name":"win7","age":9,"bir":"2012-12-12","content":"Spring的目标是致力于全方位的简化Java开发。 这势必引出更多的解释, Spring是如何简化Java开发的?","address":"南京"}
{"index":{}}
{"name":"梅超风","age":43,"bir":"2012-12-12","content":"Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API","address":"杭州"}
{"index":{}}
{"name":"张无忌","age":59,"bir":"2012-12-12","content":"ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口","address":"北京"}
6.3、URL检索
GET /ems/emp/_search?q=*&sort=age:asc
- _search:搜索的API
- q=* :匹配所有文档
- sort :以结果中的指定字段排序
- asc:排序方式(倒序or顺序)
6.4、DSL高级检索(Query)
GET /ems/emp/_search
{
"query": {"match_all": {}},
"sort": [
{
"age": {
"order": "desc"
}
}
]
}
6.4.1、match_all
这个关键字表示返回索引中的1全部文档。
GET /ems/emp/_search
{
"query": { "match_all": {} }
}
6.4.2、size
size关键字用于指定查询结果的条数,默认返回10条。
GET /ems/emp/_search
{
"query": { "match_all": {} },
"size": 1
}
6.4.3、from
from:用来指定起始返回的位置,和size连用实现分页效果。
GET /ems/emp/_search
{
"query": {"match_all": {}},
"sort": [
{
"age": {
"order": "desc"
}
}
],
"size": 2,
"from": 1
}
### 6.4.4、_source
_source是一个数组,用于指定查询结果中返回指定字段。
```markdown
GET /ems/emp/_search
{
"query": { "match_all": {} },
"_source": ["account_number", "balance"]
}
6.4.5、term
term用来使用关键词查询。
GET /ems/emp/_search
{
"query": {
"term": {
"address": {
"value": "北京"
}
}
}
}
注意事项:
- 通过使用term查询得知ES中默认使用分词器为标准分词器(StandardAnalyzer),标准分词器对于英文单词分词十分友好,但是对于中文单字分词是非常不友好的。
- 通过使用term查询得知,在ES的Mapping Type 中 keyword , date ,integer, long , double , boolean or ip 这些类型不分词,只有text类型分词。
6.4.6、range
range用来指定查询指定范围内的文档。
GET /ems/emp/_search
{
"query": {
"range": {
"age": {
"gte": 8,
"lte": 30
}
}
}
}
6.4.7、prefix
prefix用来检索含有指定前缀的关键词的相关文档。
GET /ems/emp/_search
{
"query": {
"prefix": {
"content": {
"value": "redis"
}
}
}
}
6.4.8、wildcard
wildcard用于通配符查询:
-
?
:用来匹配一个任意字符。 -
*
:用来匹配任意多个字符。
GET /ems/emp/_search
{
"query": {
"wildcard": {
"content": {
"value": "re*"
}
}
}
}
6.4.9、ids
ids关键字用来根据一组id获取多个对应的文档,他的值是数组类型。
GET /ems/emp/_search
{
"query": {
"ids": {
"values": ["lg5HwWkBxH7z6xax7W3_","lQ5HwWkBxH7z6xax7W3_"]
}
}
}
6.4.10、fuzzy
fuzzy用来模糊查询含有指定关键字的文档,他有一个最大模糊错误,必须在0~2之间:
- 搜索关键词长度为2,不允许存在模糊,最大模糊错误为0。
- 搜索关键词长度为3-5,允许一次模糊,最大模糊错误为0和1。
- 搜索关键词长度大于5,最大模糊错误为2
GET /ems/emp/_search
{
"query": {
"fuzzy": {
"content":"spring"
}
}
}
6.4.11、bool
bool关键字用来组合多个条件实现复杂查询。
GET /ems/emp/_search
{
"query": {
"bool": {
"must": [
{
"range": {
"age": {
"gte": 0,
"lte": 30
}
}
}
],
"must_not": [
{"wildcard": {
"content": {
"value": "redi?"
}
}}
]
}
},
"sort": [
{
"age": {
"order": "desc"
}
}
]
}
6.4.12、highlight
highlight关键字可以让符合条件的文档中的关键词高亮,并没有对原始数据进行高亮,他是将符合高亮的文档查询出来,并加上前后缀。我们可以自定义高亮html标签:
- pre_tags:前缀
- post_tags:后缀
GET /ems/emp/_search
{
"query":{
"term":{
"content":"框架"
}
},
"highlight": {
"pre_tags": ["<span style='color:red'>"],
"post_tags": ["</span>"],
"fields": {
"*":{}
}
}
}
如果需要多字段高亮,可以使用require_field_match
关键字将他的值设置为false开启多字段高亮。
GET /ems/emp/_search
{
"query":{
"term":{
"content":"框架"
}
},
"highlight": {
"pre_tags": ["<span style='color:red'>"],
"post_tags": ["</span>"],
"require_field_match":false,
"fields": {
"*":{}
}
}
}
6.4.13、multi_match
multi_match用于多字段查询,他需要注意的点:
- 如果搜索的字段分词,他会对query进行先分词再搜索。
- 如果搜索的字段不分词,他会直接使用query整体进行该字段搜索,建议在可分词的字段进行检索
GET /ems/emp/_search
{
"query": {
"multi_match": {
#搜索字段
"query": "中国",
#去哪些字段搜索
"fields": ["name","content"] #这里写要检索的指定字段
}
}
}
6.4.14、query_string
query_string用于多字段分词查询。
GET /dangdang/book/_search
{
"query": {
"query_string": {
"query": "中国声音",
"analyzer": "ik_max_word",
"fields": ["name","content"]
}
}
}
6.5、ElasticSearch底层原理
ElasticSearch的底层核心是倒排索引表。
索引区:对文档分词之后的结果,例如:name:[张:0:1] ("张"
这个关键字在0
号文档中出现了1
次)。
元数据区:原始放入的一个个的文档。
6.5.1、正排索引
正排表是以文档的ID为关键字,表中记录文档中每个字的位置信息,查找时扫描表中每个文档中字的信息直到找出所有包含查询关键字的文档。一般是通过key,去找value。
他的结构是 : 文档1的ID →单词1:出现次数,出现位置列表;单词2:出现次数,出现位置列表。
当用户在主页上搜索关键词“华为手机”时,假设只存在正向索引(forward index),那么就需要扫描索引库中的所有文档,找出所有包含关键词“华为手机”的文档,再根据打分模型进行打分,排出名次后呈现给用户。因为互联网上收录在搜索引擎中的文档的数目是个天文数字,这样的索引结构根本无法满足实时返回排名结果的要求。
6.5.2、倒排索引
搜索引擎会将正向索引重新构建为倒排索引,即把文件ID对应到关键词的映射转换为关键词到文件ID的映射,每个关键词都对应着一系列的文件,这些文件中都出现这个关键词。他是来利用词的关键词去找文档。
他的结构是:“关键词1”:“文档1”的ID,“文档2”的ID
七、IK分词器
ElasticSearch中采用标准分词器进行分词,这种方式并不适用于中文网站。因此需要修改ElasticSearch对中文友好分词,从而达到更佳的搜索的效果。而支持中文分词的分词器就是IK分词器。
7.1、在线安装IK分词器
将ElasticSearch服务中原始数据删除(必做)
# 进入es安装目录中将data目录数据删除
rm -rf data
安装IK分词器
# 在es安装目录中执行
./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.8.0/elasticsearch-analysis-ik-6.8.0.zip
IK分词器要求版本严格与当前使用版本一致,如需使用其他版本替换 6.2.4
为使用的版本号。
测试
GET /_analyze
{
"text": "中华人民共和国国歌",
"analyzer": "ik_smart"
}
7.2、离线安装IK分词器
可以将对应的IK分词器下载到本地,然后再安装,官网下载地址:官网直达,下面贴一张官网给的IK分词器和ElasticSearch版本对应图。
去官网下载对应版本的IK分词器
# 可以去官网下载然后上传,或者使用wegt命令,下载其他版本的修改版本号即可。
wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.2.4/elasticsearch-analysis-ik-6.2.4.zip
解压
unzip elasticsearch-analysis-ik-6.2.4.zip
移动到es安装目录的plugins目录中
mv elasticsearch elasticsearch-6.2.4/plugins/
重启ElasticSearch生效
本地安装ik分词器配置目录:es安装目录中/plugins/analysis-ik/config/IKAnalyzer.cfg.xml
测试
DELETE /ems
PUT /ems
{
"mappings":{
"emp":{
"properties":{
"name":{
"type":"text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_max_word"
},
"age":{
"type":"integer"
},
"bir":{
"type":"date"
},
"content":{
"type":"text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_max_word"
},
"address":{
"type":"keyword"
}
}
}
}
}
PUT /ems/emp/_bulk
{"index":{}}
{"name":"小黑","age":23,"bir":"2012-12-12","content":"为开发团队选择一款优秀的MVC框架是件难事儿,在众多可行的方案中决择需要很高的经验和水平","address":"北京"}
{"index":{}}
{"name":"王小黑","age":24,"bir":"2012-12-12","content":"Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式","address":"上海"}
{"index":{}}
{"name":"张小五","age":8,"bir":"2012-12-12","content":"Spring Cloud 作为Java 语言的微服务框架,它依赖于Spring Boot,有快速开发、持续交付和容易部署等特点。Spring Cloud 的组件非常多,涉及微服务的方方面面,井在开源社区Spring 和Netflix 、Pivotal 两大公司的推动下越来越完善","address":"无锡"}
{"index":{}}
{"name":"win7","age":9,"bir":"2012-12-12","content":"Spring的目标是致力于全方位的简化Java开发。 这势必引出更多的解释, Spring是如何简化Java开发的?","address":"南京"}
{"index":{}}
{"name":"梅超风","age":43,"bir":"2012-12-12","content":"Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API","address":"杭州"}
{"index":{}}
{"name":"张无忌","age":59,"bir":"2012-12-12","content":"ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口","address":"北京"}
GET /ems/emp/_search
{
"query":{
"term":{
"content":"框架"
}
},
"highlight": {
"pre_tags": ["<span style='color:red'>"],
"post_tags": ["</span>"],
"fields": {
"*":{}
}
}
}
7.3、IK分词器的类型
7.3.1、ik_max_word
ik_max_word:会将文本做最细粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,中华人民,中华,华人,人民共和国,人民,人,民,共和国,共和,和,国国,国歌”,会穷尽各种可能的组合。
7.3.2、ik_smart
ik_smart:会做最粗粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,国歌”。
7.4、配置扩展词
IK支持自定义扩展词典
和停用词典
,所谓**扩展词典
就是有些词并不是关键词,但是也希望被ES用来作为检索的关键词,可以将这些词加入扩展词典。停用词典
**就是有些词是关键词,但是出于业务场景不想使用这些关键词被检索到,可以将这些词放入停用词典。词典的编码必须为UTF-8,否则无法生效。
定义扩展词典和停用词典可以修改IK分词器中config
目录中IKAnalyzer.cfg.xml
这个文件。
修改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">ext_dict.dic</entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords">ext_stopword.dic</entry>
</properties>
在ik分词器目录下config目录中创建ext_dict.dic文件
编码一定要为UTF-8才能生效。
在ext_dict.dic中加入扩展词即可
重启ElasticSearch生效
八、Filter Query过滤查询
8.1、过滤查询
其实准确来说,ElasticSearch中的查询操作分为2种:
- 查询(query):查询即是之前提到的query查询,它 (查询)默认会计算每个返回文档的得分,然后根据得分排序。
- 过滤(filter):过滤(filter)只会筛选出符合的文档,并不计算得分,且它可以缓存文档 。
所以,单从性能考虑,过滤比查询更快。
过滤适合在大范围筛选数据,而查询则适合精确匹配数据。一般应用时, 应先使用过滤操作过滤数据, 然后使用查询匹配数据。
8.2、过滤语法
GET /ems/emp/_search
{
"query": {
"bool": {
"must": [
{"match_all": {}}
],
"filter": {
"range": {
"age": {
"gte": 10
}
}
}
}
}
}
在执行filter和query时,先执行filter再执行query。Elasticsearch会自动缓存经常使用的过滤器,以加快性能。
8.3、过滤器类型
8.3.1、term
GET /ems/emp/_search # 使用term过滤
{
"query": {
"bool": {
"must": [
{"term": {
"name": {
"value": "小黑"
}
}}
],
"filter": {
"term": {
"content":"框架"
}
}
}
}
}
8.3.2、terms
GET /dangdang/book/_search #使用terms过滤
{
"query": {
"bool": {
"must": [
{"term": {
"name": {
"value": "中国"
}
}}
],
"filter": {
"terms": {
"content":[
"科技",
"声音"
]
}
}
}
}
}
8.3.3、range
GET /ems/emp/_search
{
"query": {
"bool": {
"must": [
{"term": {
"name": {
"value": "中国"
}
}}
],
"filter": {
"range": {
"age": {
"gte": 7,
"lte": 20
}
}
}
}
}
}
8.3.4、exists
过滤存在指定字段,获取字段不为空的索引记录使用
GET /ems/emp/_search
{
"query": {
"bool": {
"must": [
{"term": {
"name": {
"value": "中国"
}
}}
],
"filter": {
"exists": {
"field":"aaa"
}
}
}
}
}
8.3.5、ids
过滤含有指定字段的索引记录。
GET /ems/emp/_search
{
"query": {
"bool": {
"must": [
{"term": {
"name": {
"value": "中国"
}
}}
],
"filter": {
"ids": {
"values": ["1","2","3"]
}
}
}
}
}
九、Java操作ElasticSearch
ElasticSearch不能够取代数据库,ElasticSearch最核心最强大的功能时完成检索,可以把给用户查询到的数据放ElasticSearch中
9.1、引入依赖
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>6.8.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>6.8.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>transport-netty4-client</artifactId>
<version>6.8.0</version>
</dependency>
9.2、创建索引和类型
PUT /dangdang
{
"mappings": {
"book":{
"properties": {
"name":{
"type":"text",
以上是关于淘宝阿里京东腾讯等一线大厂都在用的搜索引擎技术,你确定不来看看?的主要内容,如果未能解决你的问题,请参考以下文章
百度,腾讯,字节,阿里等一线大厂 Android 性能优化实战解析,Android 进阶必备技能!
为什么我轻轻松松就能拿到阿里,腾讯,京东等八家大厂offer?全靠这份pdf
全面解析Android性能优化,含腾讯阿里百度京东美团爱奇艺等大厂实战解析
抖音腾讯京东阿里等大厂性能优化方案总结(含项目实战分析及视频)