Elasticsearch简介
2016-07-07 11:34
239 查看
Elasticsearch简介
Elasticsearch是一个实时分布式搜索和分析引擎。它让你以前所未有的速度处理大数据成为可能。使用场景
全文检索结构化搜索
分析
应用
维基百科使用Elasticsearch提供全文搜索并高亮关键字,以及输入实时搜索(search-as-you-type)和搜索纠错(did-youmean)等搜索建议功能。英国卫报使用Elasticsearch结合用户日志和社交网络数据提供给他们的编辑以实时的反馈,以便及时了解公众对新发表的文章的回应。
StackOverflow结合全文搜索与地理位置查询,以及more-like-this功能来找到相关的问题和答案。
Github使用Elasticsearch检索1300亿行的代码。
Elasticsearch vs Lucene
Lucene只是一个库。想要使用它,你必须使用Java来作为开发语言并将其直接集成到你的应用中,更糟糕的是,Lucene非常复杂,你需要深入了解检索的相关知识来理解它是如何工作的。Elasticsearch也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的 RESTfulAPI 来隐藏Lucene的复杂性,从而让全文搜索变得简单。与Elasticsearch交互
Elasticsearch为Java用户提供了两种内置客户端节点客户端(node client)
节点客户端以无数据节点(none data node)身份加入集群,换言之,它自己不存储任何数据,但是它知道数据在集群中的具体位置,并且能够直接转发请求到对应的节点上。
传输客户端(Transport client)
这个更轻量的传输客户端能够发送请求到远程集群。它自己不加入集群,只是简单转发请求给集群中的节点。
两个Java客户端都通过9300端口与集群交互,使用Elasticsearch传输协议(Elasticsearch Transport Protocol)。集群中的节点
之间也通过9300端口进行通信。如果此端口未开放,你的节点将不能组成集群。
注意:Java客户端所在的Elasticsearch版本必须与集群中其他节点一致,否则,它们可能互相无法识别。
向Elasticsearch发出的请求的组成部分与其它普通的HTTP请求是一样的:
curl -X<VERB> '<PROTOCOL>://<HOST>/<PATH>?<QUERY_STRING>' -d '<BODY>'
VERB表示HTTP方法,例如: GET,POST,PUT,HEAD,DELETE
PROTOCOL表示http或者https协议(只有在Elasticsearch前面有https代理的时候可用)
HOST表示Elasticsearch集群中的任何一个节点的主机名,如果是在本地的节点,那么就叫localhost
PORT表示Elasticsearch HTTP服务所在的端口,默认为9200
QUERY_STRING表示一些可选的查询请求参数,例如 ?pretty 参数将使请求返回更加美观易读的JSON数据
BODY表示request body,一个JSON格式的请求主体(如果请求需要的话)
关系型数据库 vs Elasticsearch
Relational DB -> Databases -> Tables -> Rows -> Columns Elasticsearch -> Indices(好比数据库) -> Types(好比表) -> Documents(好比记录) -> Fields(好比列)
集群内部工作方式
集群健康:green、yellow或者redGET /_cluster/health { "cluster_name": "elasticsearch", "status": "green", <1> "timed_out": false, "number_of_nodes": 1, "number_of_data_nodes": 1, "active_primary_shards": 0, "active_shards": 0, "relocating_shards": 0, "initializing_shards": 0, "unassigned_shards": 0 }
颜色 | 意义 |
---|---|
green | 所有主要分片和复制分片都可用 |
yellow | 所有主要分片可用,但不是所有复制分片都可用 |
red | 不是所有的主要分片都可用 |
文档元数据
节点 | 说明 |
---|---|
_index | 文档存储的地方 |
_type | 文档代表的对象的类 |
_id | 文档的唯一标识 |
_index
索引,类似数据库_type
类似于”类”空搜索
GET /_search
返回集群索引中的所有文档
一些例子:
/_search
在所有索引的所有类型中搜索
/gb/_search
在索引 gb 的所有类型中搜索
/gb,us/_search
在索引 gb 和 us 的所有类型中搜索
/g*,u*/_search
在以 g 或 u 开头的索引的所有类型中搜索
/gb/user/_search
在索引 gb 的类型 user 中搜索
/gb,us/user,tweet/_search
在索引 gb 和 us 的类型为 user 和 tweet 中搜索
/_all/user,tweet/_search
在所有索引的 user 和 tweet 中搜索 search types user and tweet in all indices
分词
表征化(断词)和标准化的过程叫做分词。结构化查询 Query DSL
查询
match_all 查询使用 match_all 可以查询到所有文档,是没有查询条件下的默认语句
{ "match_all": {} }
match 查询
match 查询是一个标准查询,不管你需要全文本查询还是精确查询基本上都要用到它。
{ "match": { "tweet": "About Search" } }
multi_match 查询
multi_match 查询允许你做 match 查询的基础上同时搜索多个字段
{
“multi_match”: {
“query”: “full text search”,
“fields”: [ “title”, “body” ]
}
}
bool 查询
bool 查询与 bool 过滤相似,用于合并多个查询子句。不同的是, bool 过滤可以直接给出是否匹配成功, 而 bool 查询要计算每一个查询子句的 _score (相关性分值)
语句 | 含义 |
---|---|
must | 查询指定文档一定要被包含。 |
must_not | 查询指定文档一定不要被包含。 |
should | 查询指定文档,有则可以为文档相关性加分。 |
“bool”: {
“must”: { “match”: { “title”: “how to make millions” }},
“must_not”: { “match”: { “tag”: “spam” }},
“should”: [
{ “match”: { “tag”: “starred” }},
{ “range”: { “date”: { “gte”: “2014-01-01” }}}
]
}
}
过滤
term 过滤term 主要用于精确匹配哪些值,比如数字,日期,布尔值或 not_analyzed 的字符串(未经分析的文本数据类型)
{ "term": { "age": 26 } }
terms 过滤
terms 跟 term 有点类似,但 terms 允许指定多个匹配条件。 如果某个字段指定了多个值,那么文档需要一起去做匹配
{ "terms": { "tag": ["search", "full_text", "nosql"] } }
range 过滤
range 过滤允许我们按照指定范围查找一批数据
{ "range": { "age": { "gte": 20, "lt": 30 } } }
范围操作符包含:
符号 | 含义 |
---|---|
gt | 大于 |
gte | 大于等于 |
lt | 小于 |
lte | 小于等于 |
exists 和 missing 过滤可以用于查找文档中是否包含指定字段或没有某个字段,类似于SQL语句中的 IS_NULL 条件
{ "exists": { "field": "title" } }
bool 过滤
bool 过滤可以用来合并多个过滤条件查询结果的布尔逻辑,它包含一下操作符:
语句 | 含义 |
---|---|
must | 多个查询条件的完全匹配,相当于 and 。 |
must_not | 多个查询条件的相反匹配,相当于 not 。 |
should | 至少有一个查询条件匹配, 相当于 or 。 |
{ "bool": { "must": { "term": { "folder": "inbox" }}, "must_not": { "term": { "tag": "spam" }}, "should": [ { "term": { "starred": true }}, { "term": { "unread": true }} ] } }
查询与过滤条
c5cb
件的合并
举例:查询语句
{ "match": { "email": "business opportunity" } }
然后我们想要让这条语句加入 term 过滤,在收信箱中匹配邮件
{ "term": { "folder": "inbox" } }
search API中只能包含 query 语句,所以我们需要用 filtered 来同时包含 “query” 和 “filter” 子句
{ "filtered": { "query": { "match": { "email": "business opportunity" }}, "filter": { "term": { "folder": "inbox" }} } }
理解错误信息
想知道语句非法的具体错误信息,需要加上 explain 参数例如:
GET /gb/tweet/_validate/query?explain
返回的结果中valid为false表示不合法。假设合法的话,返回true,explanations就是查询的过程了
{ "valid" : false, "_shards" : { ... }, "explanations" : [ { "index" : "gb", "valid" : false, "error" : "org.elasticsearch.index.query.QueryParsingException:[gb] No query registered for [tweet]" } ] }
相关性排序
字段值排序对结果集按照时间排序,这也是最常见的情形,将最新的文档排列靠前。 我们使用 sort 参数进行排序
GET /_search{
"query" : {
"filtered" : {
"filter" : { "term" : { "user_id" : 1 }}
}
},
"sort": { "date": { "order": "desc" }}
}
有了sort后,就不需要对_score进行计算了。计算 _score 是比较消耗性能的, 而且通常主要用作排序 – 我们不是用相关性进行排序的时候,就不需要统计其相关性。
默认排序
字段值默认以顺序排序,_score默认以倒序排序
多级排序
结果集会先用第一排序字段来排序,当用用作第一字段排序的值相同的时候, 然后再用第二字段对第一排序值相同的文档进行排序,以此类推。
GET /_search{
"query" : {
"filtered" : {
"query": { "match": { "tweet": "manage text search" }},
"filter" : { "term" : { "user_id" : 2 }}
}
},
"sort": [
{ "date": { "order": "desc" }},
{ "_score": { "order": "desc" }}
]
}
正向相关和反向相关
检索词频率:出现频率越高,相关性也越高反向文档频率:频率越高,相关性越低
字段长度准则:长度越长,相关性越低
重要: 输出 explain 结果代价是十分昂贵的,它只能用作调试工具 –千万不要用于生产环境。
扫描和滚屏
scan(扫描) 搜索类型是和 scroll(滚屏) API一起使用来从Elasticsearch里高效地取回巨大数量的结果而不需要付出深分页的代价。scroll(滚屏)
一个滚屏搜索允许我们做一个初始阶段搜索并且持续批量从Elasticsearch里拉取结果直到没有结果剩下。这有点像传统数据
库里的cursors(游标)。
scan(扫描)
深度分页代价最高的部分是对结果的全局排序,但如果禁用排序,就能以很低的代价获得全部返回结果。为达成这个目的,可以采用 scan(扫描) 搜索模式。扫描模式让Elasticsearch不排序,只要分片里还有结果可以返回,就返回一批结果。
配置
number_of_shards:定义一个索引的主分片个数number_of_replicas:每个主分片的复制分片个数
配置分析器
standard 分析器是用于全文字段的默认分析器,对于大部分西方语系来说是一个不错的选择。它考虑了以下几点standard 分词器,在词层级上分割输入的文本。
standard 表征过滤器,被设计用来整理分词器触发的所有表征(但是目前什么都没做)。
lowercase 表征过滤器,将所有表征转换为小写。
stop 表征过滤器,删除所有可能会造成搜索歧义的停用词,如 a , the , and , is 。
stemmer 表征过滤器将单词转化为他们的根形态
将 & 替换成 and ,使用一个自定义的 mapping 字符过滤器
"char_filter": { "&_to_and": { "type": "mapping", "mappings": [ "&=> and "] } }
索引别名
索引 别名 就像一个快捷方式或软连接,可以指向一个或多个索引,也可以给任何需要索引名的 API 使用。别名带给我们极大的灵活性,允许我们做到:在一个运行的集群上无缝的从一个索引切换到另一个
给多个索引分类(例如, last_three_months )
给索引的一个子集创建 视图
在应用中使用别名而不是索引。然后你就可以在任何时候重建索引。别名的开销很小,应当广泛使用。
相关文章推荐
- SQL Server全文检索查询浅析
- 巧用mysql提示符prompt清晰管理数据库的方法
- 两大步骤教您开启MySQL 数据库远程登陆帐号的方法
- phpmyadmin 4+ 访问慢的解决方法
- linux系统下实现mysql热备份详细步骤(mysql主从复制)
- CentOS 5.5下安装MySQL 5.5全过程分享
- MySQL复制的概述、安装、故障、技巧、工具(火丁分享)
- MySQL中删除重复数据的简单方法
- MySQL5.5.21安装配置教程(win7)
- 使用ElasticSearch6.0快速实现全文搜索功能的示例代码
- elasticsearch批量数据导入和导出
- 使用ElasticSearch+LogStash+Kibana+Redis搭建日志管理服务
- ElasticSearch 使用心得
- ES中如何使用逗号来分词
- ElasticSearch 守护进程 JSW
- elasticsearch2.3安装以及集群部署
- elasticsearch增删改查
- Elasticsearch2.2.0数据操作
- Elasticsearch2.2.0安装ik中文分词
- Elasticsearch2.2.0安装pinyin插件