搜索面临的问题
几乎每一个网站都会有全文检索功能,全文检索与传达的sql查询有很大的区别,sql查询一般是从结构化数据中查询指定的数据,而全文检索是从海量的非结构化数据中查询出匹配的数据,而且对查询速度的要求非常高,同时还要支持海量数据的统计分析能力。
ES是一个基于Lucene的分布式海量数据搜索引擎,它提供了简单的resut api访问接口、支持大规模集群部署、能够提供几乎实时的查询、具有数据统计分析功能,同时还有大量的第三方插件来丰富es的功能。
ES的使用场景
- 站内搜索、自动补全
- 日志分析
- 数据预警(Machine Learning)
- 数据分析
ES的基础原理
ES底层基于Lucene,对数据进行分片存储,通知对分片提供副本冗余,保证数据的安全性。
一般情况下,我们会领域JavaApplication/Flume等工具从其他数据源总拉取数据,然后将其写入ES中,ES中的数据是存在在索引库中的,索引库相当于RDB中的一张表,在写入数据前我们要先创建索引库
,然后将待写入数据构造成索引文档(Document)
,索引文档相当于RDB中的一条记录,包含了多个Field
,每个Field可以有不同了类型,然后ES会多Filed进行分词,构造倒排索引
,最终将原始数据写入索引库
,对于索引,一般会进行大小写转换
、停用词
处理等。
为了快速检索到对应的数据,每个分词后面会挂接一个``链表或B树,用来存储与这个词相关的文档,链表或索引树的每个节点中存储了
文档ID和词频率```,
当用户进行数据查询时,ES首先会对查询条件进行分词处理,然后匹配分词索引,最终找到对应的Document,需要说明的是,Document中的Field字段的设计实际上是根据业务需求来自定义的,客户端需要哪些数据,在设计的时候就需要存储哪些数据。
以李白的静夜思为例,如果我们想把这首诗存储到es中,并提供对应的搜索功能,那么,我们就可以在设计Ducoment时,指定作者、标题、内容、创建时间等Filed字段,当写入数据的时候,ES会多每个字段进行分词,分词后的每个词会与这个Document进行关联,当我们用指定的词语进行查询时,最终就能够关联到这首李白的静夜思了。
ES提供了集群部署方案,数据会以主分片+副本分片的方式进行存储,主分片直接与数据读写交互,副本分别负责对主分片进行备份,分片数据和复本数在床架索引库时指定,需要注意的是,在设置分片数的时候要预估数据的容量,因为分片树一般不会进行修改,也即是说,如果集群进行扩容的话,如果不修改分片树,该索引库将无法利用新增的节点进行数据存储。
概念说明
- 文档:Document,是ES中可以被搜索到的数据的最小单元,每个文档都有一个唯一的文档ID,可以自己指定,也可以让ES自动生成。
- 索引:索引指的是一类文档的集合,这里的索引指的是索引库,也就是存储Document的地方,类似于RDB中的表,在定义索引的时候可以设置mapping和setting,mapping定义了索引库包含哪些字段,类似于RDB中表的Schema,setting定义了一些物理存储特性,例如分片数和副本数等。
- 分片:分片分为主分片和副本分片,通过分片可以解决集群能力扩展的问题,通过调整分片数量来将数据均匀的分布到不同节点上,副本分片主要解决了数据的可用性问题,防止数据丢失。
- 倒排索引:与倒排索引相反的是正排索引,即文档ID->文档, 倒排索引的文档中的单词->文档ID,在es中采用倒排索引来存储分词,分词词典(单词) -> [docID, wordFrequency] -> [docID, wordFrequency])(哈希拉链)。
一些rest api
## 按空格拆分, 大写转小写
get _analyze
{
"analyzer":"standard",
"text":"2 running Quick brown-foxes leap over lazy dogs in the summer evening"
}
#按空格拆分,大写转消息,处理停用词
get _analyze
{
"analyzer":"simple",
"text":"2 running Quick brown-foxes leap over lazy dogs in the summer evening"
}
#按空格拆分
get _analyze
{
"analyzer":"whitespace",
"text":"2 running Quick brown-foxes leap over lazy dogs in the summer evening"
}
#去掉一些非语义词 2、in等,大写转小写
get _analyze
{
"analyzer":"stop",
"text":"2 running Quick brown-foxes leap over lazy dogs in the summer evening"
}
## ik 中文分词器
get _analyze
{
"analyzer":"ik_smart",
"text":"我是中国人"
}
URL Search
# /_search #查询所有的索引
# indexname/_search 查询指定索引
# indexname1,indexname2/_search 查询多个索引
# index*/_search #正则匹配查询索引
get goods/_search
get _search
get /movie/_search?q=2012&df=title&sort=year:desc&from=0&size=10&timeout=1s
{
"profile":true
}
# q : 指定查询时条件的值
# df : 指定要查询哪个字段
# sort : 指定排序字段及排序方式
# from / size : 分页
# profile : 显示执行计划
Request Body Search
http://localhost:9200/goods/_search
{
"query":{
"match_all":{}
}
}
http://localhost:9200/goods/_search #goodsName 包含三星的数据
{
"query":{
"match":{
"goodsName":{
"query":"三星"
}
}
}
}