赞
踩
在数据驱动的时代,Elasticsearch以其卓越的全文搜索能力和分布式架构,成为处理海量数据的关键工具。本博客将带您从Elasticsearch的基础概念出发,深入解析其核心——倒排索引,并介绍如何在Docker中轻松部署。我们将详细讲解Elasticsearch的基础语法,确保能够掌握其操作精髓。最后,通过一个实战案例——构建课程搜索与数据同步接口,体验Elasticsearch在实际项目中的强大功能。
Elasticsearch(简称ES)是一个基于Lucene构建的开源、分布式、RESTful的搜索和分析引擎。 它以其强大的全文搜索能力、高可用性、可扩展性和易用性而广受欢迎,被广泛应用于各种规模的企业和组织中。
倒排索引 是 Elasticsearch 及其底层 Lucene 引擎实现快速搜索的关键技术。在传统的数据库中,我们是通过文档(或记录)来查找包含特定关键词的文档列表。而在搜索引擎中,这个过程被逆转了:我们根据关键词来查找包含这些关键词的文档列表。这就是“倒排索引”的由来。
倒排索引是区别于正排索引的概念:
- 正排索引:是以文档对象的唯一 ID 作为索引,以文档内容作为记录。
- 倒排索引:Inverted index,指的是将文档内容中的单词作为索引,将包含该词的文档 ID 作为记录。
倒排索引的结构
根据倒排索引的概念,我们可以用一个 Map来简单描述这个结构。这个Map
的Key
的即是分词后的单词,这里的单词称为Term
,这一系列的 Term 组成了倒排索引的第一个部分 ——Term Dictionary
(索引表,可简称为 Dictionary)。
倒排索引的另一部分为Postings List
(记录表),也对应上述Map
结构的Value
部分集合。
记录表 由所有的Term
对应的数据(Postings
) 组成,它不仅仅为文档id
信息,可能包含以下信息:
- 文档 id(DocId, Document Id),包含单词的所有文档唯一 id,用于去正排索引中查询原始数据。
- 词频(TF,Term Frequency),记录 Term 在每篇文档中出现的次数,用于后续相关性算分。
- 位置(Position),记录 Term 在每篇文档中的分词位置(多个),用于做词语搜索(Phrase Query)。
- 偏移(Offset),记录 Term 在每篇文档的开始和结束位置,用于高亮显示等。
升级所有包同时也升级软件和系统内核:
yum -y update
只升级所有包,不升级软件和系统内核:
yum -y upgrade
删除自带的docker
yum remove docker docker-common docker-selinux docker-engine
安装需要的软件包, yum-util 提供yum-config-manager功能,另两个是devicemapper驱动依赖
yum install -y yum-utils device-mapper-persistent-data lvm2
设置一个yum源,下面两个都可用,选择一个
yum-config-manager --add-repo http://download.docker.com/linux/centos/docker-ce.repo(中央仓库)
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo(阿里仓库)
查看docker可用版本
yum list docker-ce --showduplicates | sort -r
安装docker
yum -y install docker-ce-18.03.1.ce
设置开机启动
systemctl start docker
systemctl enable docker
docker 拉取 elasticsearch镜像
docker pull elasticsearch:7.7.0
docker pull docker.elastic.co/elasticsearch/elasticsearch:7.7.0
docker 运行 elasticsearch
docker run --name elasticsearch -d -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -e "discovery.type=single-node" -p 9200:9200 -p 9300:9300 elasticsearch:7.7.0
发送put请求: http://localhost:9200/shopping
发送get请求: http://localhost:9200/shopping
查看所有索引 http://localhost:9200/_cat/indices?v
发送delete请求 http://localhost:9200/shopping
发送post请求 http://localhost:9200/shopping/_doc
请求体Body:
{
"name":"张三",
"age":10,
"category":1,
"status":1,
"online":2
}
幂等性操作
- 添加时添加id ,http://localhost:9200/shopping/_doc/1001
发送get请求
查询单个 http://localhost:9200/shopping/_doc/1002
查询全部 http://localhost:9200/shopping/_search
完全覆盖
- 发送put请求 http://localhost:9200/shopping/_doc/1001
修改某个属性
- 发送post请求 http://localhost:9200/shopping/_update/1001
发送post请求 http://localhost:9200/shopping/_update/1001
{
"doc": {
"name": "张三22"
}
}
完全覆盖
- 发送delete请求 http://localhost:9200/shopping/_doc/1001
get http://localhost:9200/shopping/_search
{
"query":{
"match":{"category":1}
}
}
查询category为1的数据:
查询所有数据
{
"query":{
"match_all":{}
}
}
查询所有数据:
{
"query":{
"match_all":{}
},
"from":0,
"size":2
}
指定name姓名字段
{
"query":{
"match_all":{}
},
"from":0,
"size":2,
"_source":["name"]
}
指定name姓名字段:
{
"query":{
"match_all":{}
},
"from":0,
"size":2,
"_source":["name","age"],
"sort":{
"id":{
"order":"desc"
}
}
}
{
"query":{
"bool":{
"must":[
{"match":{"age":10}},
{"match":{"name":"张三"}}
]
}
},
"from":0,
"size":2,
"_source":["name","age"],
"sort":{
"age":{
"order":"desc"
}
}
}
select * from users where age=10 and name="张三"
select * from users where age=10 and name=“张三”
{
"query":{
"bool":{
"should":[
{"match":{"age":10}},
{"match":{"name":"张三"}}
]
}
},
"from":0,
"size":2,
"_source":["name","age"],
"sort":{
"age":{
"order":"desc"
}
}
}
select * from users where age=10 or name="张三"
select * from users where age=10 or name=“张三”
es支持常用的语法,通过
- from size进行分页查询,
- match条件查询,
- _source指定返回字段,
- sort排序,
- range进行区间查询,
- must并且查询,
- should进行或查询
{
"query":{
"bool":{
"should":[
{"match":{"age":10}},
{"match":{"name":"张三"}}
],
"filter":{
"range":{
"age":{"gt":3}
}
}
}
},
"from":0,
"size":2,
"_source":["name","age"],
"sort":{
"age":{
"order":"desc"
}
}
}
使用es查询课程信息:
- 1.实例化Elasticsearch类
- 2.es.index创建索引,把记录添加到es中
- 3.先mysql中的数据加载到es中,第一次全量式同步,后面增量式同步
- 4.用es._search从查询数据
下面代码示例展示了如何使用Django REST framework的APIView以及Elasticsearch客户端来实现一个简单的课程搜索和数据同步接口。
#course/views.py
#demo:es
from elasticsearch import Elasticsearch
es = Elasticsearch("http://localhost:9200/")
class CourseSearchEs(APIView):
#对课程构建索引
def get(self, request):
dsl = {
"query":{
"match":{}
},
'from':0,
'size':2,
'_source':['id','name','sales']
}
res = es.search(index="ccourse", body=dsl)
data = res['hits']['hits']
clist = []
for i in data:
clist.append(i['_source'])
return Response({"code": "200", "data": clist})
def post(self, request):
# 查询课程中所有数据
course = CourseModel.objects.all()
# 数据同步---全量式同步
for c in course:
es.index(index='ccourse',body={
'id': c.id,
'table_name':'course',
'name':c.name,
'sales':c.sales,
'describe':c.describe,
})
r.setex_str('id',60*60,c.id) #会覆盖,只存最后一次id(最大id)
return Response({"code": "200"})
# base/tasks.py
@shared_task
def syn_mysql_es():
es = Elasticsearch("http://120.46.9.231:9200/")
# 查询上次最终更新课程id后的所有数据
cid = r.get_str("id")
print(cid)
course = CourseModel.objects.filter(id__gt=cid)
# 数据同步---增量式同步(定时同步数据)
for c in course:
es.index(index='ccourse', body={
'id': c.id,
'table_name': 'course',
'name': c.name,
'sales': c.sales,
'describe': c.describe,
})
r.setex_str('id', 60 * 60, c.id)
print("mysql_es_数据同步完成...")
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。