简介
Elasticsearch是面向文档(document oriented)的,这意味着它可以存储整个对象或文档(document)。然而它不仅仅是存储,还会索引(index)每个文档的内容使之可以被搜索。在Elasticsearch中,你可以对文档(而非成行成列的数据) 进行索引、搜索、排序、过滤。这种理解数据的方式与以往完全不同,这也是Elasticsearch能够执行复杂的全文搜索的原因之一。
序列化格式
ELasticsearch使用Javascript对象符号(JavaScript Object Notation),也就是JSON,作为文档序列化格式。在Elasticsearch中存储数据的行为就叫做索引(indexing)
关系型数据库与nosql数据库
Relational DB -> Databases -> Tables -> Rows -> Columns
Elasticsearch -> Indices -> Types -> Documents -> Fields
操作
增
们看到path: /megacorp/employee/1 包含三部分信息:
megacorp --- 索引名
employee --- 类型名
1 --- 这个员工的ID
请求示例:
PUT /megacorp/employee/1
{
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
检索文档
1.简单搜索
GET /megacorp/employee/1
- 过滤器(filter),它使得我们高效率的执行一个结构化搜索:
post /dcp_crm_dev_20180109/_search
{
"from": 0,
"size": 11,
"query": {
"filtered": {
"query": {
"bool": {}
},
"filter": {
"bool": {
"must": {
"and": {
"filters": [
{
"range": {
"ctime": {
"gte": "1521561600",
"lt": "1524211550"
}
}
},
{
"term": {
"status": "1"
}
}
]
}
},
"_cache": true
}
}
}
},
"_source": {
"includes": [
"com_id",
"status",
"ctime"
],
"excludes": []
},
"sort": [
{
"com_id": {
"order": "desc"
}
}
]
}
- 全文搜索
post /megacorp/employee/_search
{
"query": {
"match": {
"about": "rock climbing"
}
}
}
结构化查询
结构化查询是一种灵活的,多表现形式的查询语言。 Elasticsearch在一个简单的JSON接口中
用结构化查询来展现Lucene绝大多数能力。 你应当在你的产品中采用这种方式进行查询。它
使得你的查询更加灵活,精准,易于阅读并且易于debug。
post /dcp_crm_dev_20180109/_search
{
"from": 0,
"size": 11,
"query": { //结构化查询需要
"filtered": { //查询子句
"query": { //查询子句
"bool": {}
},
"filter": {
"bool": {
"must": {
"and": {
"filters": [
{
"range": {
"ctime": {
"gte": "1521561600",
"lt": "1524211550"
}
}
},
{
"term": {
"status": "1"
}
}
]
}
},
"_cache": true
}
}
}
},
"_source": {
"includes": [
"com_id",
"status",
"ctime"
],
"excludes": []
},
"sort": [
{
"com_id": {
"order": "desc"
}
}
]
}
结果
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 182,
"max_score": null,
"hits": [
{
"_index": "diary_v1803019",
"_type": "scene",
"_id": "1583335",
"_score": null, //相关性评分
"_source": {
"com_id": 1677265,
"ctime": 1523178052,
"status": 1
},
"sort": [
1677265
]
},
{
"_index": "diary_v1803019",
"_type": "scene",
"_id": "1583342",
"_score": null,
"_source": {
"com_id": 1677265,
"ctime": 1523181594,
"status": 1
},
"sort": [
1677265
]
}
]
}
}
查询子句:
1.叶子子句(leaf clauses)(比如 match 子句)用以在将查询字符串与一个字段(或多字段)进行比较
2.复合子句(compound)用以合并其他的子句。例如, bool 子句允许你合并其他的合法子句, must , must_not 或者 should ,如果可能的话:
查询与过滤
结构化查询(Query DSL) 和结构化过滤(Filter DSL)
一条过滤语句会询问每个文档的字段值是否包含着特定值:
查询语句会询问每个文档的字段值与特定值的匹配程度如何?
性能差异
使用过滤语句得到的结果集 -- 一个简单的文档列表,快速匹配运算并存入内存是十分方便的, 每个文档仅需要1个字节。这些缓存的过滤结果集与后续请求的结合使用是非常高效的。
查询语句不仅要查找相匹配的文档,还需要计算每个文档的相关性,所以一般来说查询语句要比 过滤语句更耗时,并且查询结果也不可缓存。
幸亏有了倒排索引,一个只匹配少量文档的简单查询语句在百万级文档中的查询效率会与一条经过缓存 的过滤语句旗鼓相当,甚至略占上风。 但是一般情况下,一条经过缓存的过滤查询要远胜一条查询语句的执行效率
使用规则
原则上来说,使用查询语句做全文本搜索或其他需要进行相关性评分的时候,剩下的全部用过滤语句
过滤语句
term 主要用于精确匹配哪些值,比如数字,日期,布尔值或 not_analyzed 的字符串(未经分析的文本数据类型):
{ "term": { "age": 26 }}
{ "term": { "date": "2014-09-01" }}
{ "term": { "public": true }}
{ "term": { "tag": "full_text" }}
terms 跟 term 有点类似,但 terms 允许指定多个匹配条件。 如果某个字段指定了多个值,那么文档需要一起去做匹配:
{
"terms": {
"tag": [ "search", "full_text", "nosql" ]
}
}
range 过滤允许我们按照指定范围查找一批数据:
{
"range": {
"age": {
"gte": 20,
"lt": 30
}
}
}
gt :: 大于
gte :: 大于等于
lt :: 小于
lte :: 小于等于
exists 和 missing 过滤可以用于查找文档中是否包含指定字段或没有某个字段,类似于SQL语句中的 IS_NULL 条件
{
"exists": {
"field": "title"
}
}
bool 过滤可以用来合并多个过滤条件查询结果的布尔逻辑,它包含一下操作符:
must :: 多个查询条件的完全匹配,相当于 and 。
must_not :: 多个查询条件的相反匹配,相当于 not 。
should :: 至少有一个查询条件匹配, 相当于 or 。
这些参数可以分别继承一个过滤条件或者一个过滤条件的数组:
查询
使用 match_all 可以查询到所有文档,是没有查询条件下的默认语句。
"match_all": {}
}
match 查询是一个标准查询,不管你需要全文本查询还是精确查询基本上都要用到它。用 match 下指定了一个确切值,在遇到数字,日期,布尔值或者 not_analyzed 的字符串
时,它将为你搜索你给定的值:
{ "match": { "age": 26 }}
{ "match": { "date": "2014-09-01" }}
{ "match": { "public": true }}
{ "match": { "tag": "full_text" }}
multi_match 查询允许你做 match 查询的基础上同时搜索多个字段
{
"multi_match": {
"query": "full text search",
"fields": [ "title", "body" ]
}
}
bool 查询与 bool 过滤相似,用于合并多个查询子句。不同的是, bool 过滤可以直接给
出是否匹配成功, 而 bool 查询要计算每一个查询子句的 _score (相关性分值) 。
search API中只能包含 query 语句,所以我们需要用 filtered 来同时包含 "query" 和
"filter" 子句:
{
"query": {
"filtered": {
"query": { "match": { "email": "business opportunity" } },
"filter": { "term": { "folder": "inbox" } }
}
}
}
有关名词
索引
索引(名词) 如上文所述,一个索引(index)就像是传统关系数据库中的数据库,它是相关文档存储的地方,index的复数是indices 或indexes。
索引(动词) 「索引一个文档」 表示把一个文档存储到索引(名词) 里,以便它可以被检索或者查询。这很像SQL中的 INSERT 关键字,差别是,如果文档已经存在,新的文档将覆盖旧的文档。
倒排索引 传统数据库为特定列增加一个索引,例如B-Tree索引来加速检索。Elasticsearch和Lucene使用一种叫做倒排索引(inverted index)的数据结构来达到相同目的。
DSL
DSL(Domain Specific Language特定领域语言)
网友评论