pretty
在任意的查询字符串中增加pretty参数,会让Elasticsearch美化输出(pretty-print)JSON响应以便更加容易阅读。
GET /website/blog/123?pretty
针对性过滤输出
GET /website/blog/123?_source=title,text
如果你想做的只是检查文档是否存在,使用HEAD方法来代替GET。HEAD请求不会返回响应体,只有HTTP头:
curl -i -XHEAD http://localhost:9200/website/blog/123
HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Content-Length: 0
请求成功的创建了一个新文档,Elasticsearch将返回正常的元数据且响应状态码是201 Created,如果文档已存在,Elasticsearch将返回409 Conflict响应状态码。
解决冲突:
1.在读一行数据前锁定这行,然后确保只有加锁的那个线程可以修改这行数据。
2.在读写过程中数据发生了变化,更新操作将失败。这时候由程序决定在失败后如何解决冲突。实际情况中,可以重新尝试更新,刷新数据(重新读取)或者直接反馈给用户。
如果需要从Elasticsearch中检索多个文档,相对于一个一个的检索,更快的方式是在一个请求中使用multi-get或者mget API。mget是针对读,针对所有主从分片。
POST /_mget
{
"docs" : [
{
"_index" : "website",
"_type" : "blog",
"_id" : 2
},
{
"_index" : "website",
"_type" : "pageviews",
"_id" : 1,
"_source": "views"
}
]
}
bulk API允许我们使用单一请求来实现多个文档的create、index、update或delete。针对主分片操作。
POST /_bulk
{ "create": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "title": "Cannot create - it already exists" }
{ "index": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "title": "But we can update it" }
整个批量请求需要被加载到接受我们请求节点的内存里,所以请求越大,给其它请求可用的内存就越小。有一个最佳的bulk请求大小。超过这个大小,性能不再提升而且可能降低。
路由文档到分片
当你索引一个文档,它被存储在单独一个主分片上。Elasticsearch是如何知道文档属于哪个分片的呢?当你创建一个新文档,它是如何知道是应该存储在分片1还是分片2上的呢?
进程不能是随机的,因为我们将来要检索文档。事实上,它根据一个简单的算法决定:
shard = hash(routing) % number_of_primary_shards
routing值是一个任意字符串,它默认是_id但也可以自定义。这个routing字符串通过哈希函数生成一个数字,然后除以主切片的数量得到一个余数(remainder),余数的范围永远是0到
number_of_primary_shards - 1,这个数字就是特定文档所在的分片。
这也解释了为什么主分片的数量只能在创建索引时定义且不能修改:如果主分片的数量在未来改变了,所有先前的路由值就失效了,文档也就永远找不到了。
replication复制
复制默认的值是sync。这将导致主分片得到复制分片的成功响应后才返回。设置replication为async,请求在主分片上被执行后就会返回给客户端。它依旧会转发请求给复制节点,但将不知道复制
节点成功与否。
consistency
默认主分片在尝试写入时需要规定数量(quorum)或过半的分片(可以是主节点或复制节点)可用。
int( (primary + number_of_replicas) / 2 ) + 1 number_of_replicas是复制分片的数量。
数据检索
1.客户端给Node 1发送get请求。
2.节点使用文档的_id确定文档属于分片0。分片0对应的复制分片在三个节点上都有。负载均衡转发请求到Node 2。
3.Node 2返回文档(document)给Node 1然后返回给客户端。
搜索:
hits:响应中最重要的部分是hits,它包含了total字段来表示匹配到的文档总数,hits数组还包含了匹配到的前10条数据。每个节点都有一个_score字段,这是相关性得分(relevance score),
它衡量了文档与查询的匹配程度。按照_score降序排列的
took告诉我们整个搜索请求花费的毫秒数。
time_out值告诉我们查询超时与否。
{
"hits" : {
"total" : 14,
"hits" : [
{
"_index": "us",
"_type": "tweet",
"_id": "7",
"_score": 1,
"_source": {
"date": "2014-09-17",
"name": "John Smith",
"tweet": "The Query DSL is really powerful and flexible",
"user_id": 2
}
},
... 9 RESULTS REMOVED ...
],
"max_score" : 1
},
"took" : 4,
"_shards" : {
"failed" : 0,
"successful" : 10,
"total" : 10
},
"timed_out" : false
}
多索引和多类别:
GET /_all/tweet/_search?q=tweet:elasticsearch _all:所有文档
/_search
在所有索引的所有类型中搜索
/gb/_search
在索引gb的所有类型中搜索
/gb,us/_search
在索引gb和us的所有类型中搜索
/g*,u*/_search
在以g或u开头的索引的所有类型中搜索
Elasticsearch分页展示,接受from和size参数:
size: 结果数,默认10
from: 跳过开始的结果数,默认0
如果你想每页显示5个结果,页码从1到3,那请求如下:
GET /_search?size=5
GET /_search?size=5&from=5
GET /_search?size=5&from=10
映射(mapping)机制用于进行字段类型确认,将每个字段匹配为一种确定的数据类型(string, number, booleans, date等)。
分析(analysis)机制用于进行全文文本(Full Text)的分词,以建立供搜索用的反向索引。
例:Elasticsearch在对gb索引中的tweet类型进行mapping,Elasticsearch为对字段类型进行猜测,动态生成了字段和类型的映射关系
date类型的字段和string类型的字段的索引方式是不同的,查询匹配日期结果也是不同的。
{
"gb": {
"mappings": {
"tweet": {
"properties": {
"date": {
"type": "date",
"format": "dateOptionalTime"
},
"name": {
"type": "string"
},
"tweet": {
"type": "string"
},
"user_id": {
"type": "long"
}
}
}
}
}
}
Elasticsearch中的数据可以大致分为两种类型:
确切值确定的,正如它的名字一样。比如一个date或用户ID,确切值"Foo"和"foo"就并不相同。确切值2014和2014-09-15也不相同。
全文文本,文本化的数据,全文文本常常被称为非结构化数据,匹配程度查询,例如一封邮件
分析器:
当你查询全文(full text)字段,查询将使用相同的分析器来分析查询字符串,以产生正确的词列表。全文检索需要分词。
当你查询一个确切值(exact value)字段,查询将不分析查询字符串,但是你可以自己指定。确切值查询不需要分词。
Elasticsearch支持以下简单字段类型:
类型 表示的数据类型
String string
Whole number byte, short, integer, long
Floating point float, double
Boolean boolean
Date date
查看映射:
GET /gb/_mapping/tweet
index值 解释
analyzed 首先分析这个字符串,然后索引。换言之,以全文形式索引此字段。
not_analyzed 索引这个字段,使之可以被搜索,但是索引内容和指定值一样。不分析此字段。
no 不索引这个字段。这个字段不能为搜索到。
string类型字段默认值是analyzed。如果我们想映射字段为确切值,我们需要设置它为not_analyzed:
{
"tag": {
"type": "string",
"index": "not_analyzed"
}
}
叶子子句(leaf clauses)(比如match子句)用以在将查询字符串与一个字段(或多字段)进行比较
复合子句(compound)用以合并其他的子句。例如,bool子句允许你合并其他的合法子句,must,must_not或者should,如果可能的话:
{
"bool": {
"must": { "match": { "tweet": "elasticsearch" }},
"must_not": { "match": { "name": "mary" }},
"should": { "match": { "tweet": "full text" }}
}
}
must :: 多个查询条件的完全匹配,相当于 and。
must_not :: 多个查询条件的相反匹配,相当于 not。
should :: 至少有一个查询条件匹配, 相当于 or。
结构化查询(Query DSL)查询语句会询问每个文档的字段值与特定值的匹配程度如何
结构化过滤(Filter DSL)一条过滤语句会询问每个文档的字段值是否包含着特定值
最常用到的查询过滤语句:
term主要用于精确匹配哪些值,比如数字,日期,布尔值或 not_analyzed的字符串(未经分析的文本数据类型)
terms 跟 term 有点类似,但 terms 允许指定多个匹配条件。
range过滤允许我们按照指定范围查找一批数据
范围操作符包含:
gt :: 大于
gte:: 大于等于
lt :: 小于
lte:: 小于等于
exists 和 missing 过滤可以用于查找文档中是否包含指定字段或没有某个字段
validate API 可以验证一条查询语句是否合法。
GET /gb/tweet/_validate/query
{
"query": {
"tweet" : {
"match" : "really powerful"
}
}
}
以上请求的返回值告诉我们这条语句是非法的:
{
"valid" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"failed" : 0
}
}
理解查询语句:使用 explain 参数可以返回一个带有查询语句的可阅读描述
GET /_validate/query?explain
{
"query": {
"match" : {
"tweet" : "really powerful"
}
}
}
explanation 会为每一个索引返回一段描述,因为每个索引会有不同的映射关系和分析器:
{
"valid" : true,
"_shards" : { ... },
"explanations" : [ {
"index" : "us",
"valid" : true,
"explanation" : "tweet:really tweet:powerful"
}, {
"index" : "gb",
"valid" : true,
"explanation" : "tweet:really tweet:power"
} ]
}
在任意的查询字符串中增加pretty参数,会让Elasticsearch美化输出(pretty-print)JSON响应以便更加容易阅读。
GET /website/blog/123?pretty
针对性过滤输出
GET /website/blog/123?_source=title,text
如果你想做的只是检查文档是否存在,使用HEAD方法来代替GET。HEAD请求不会返回响应体,只有HTTP头:
curl -i -XHEAD http://localhost:9200/website/blog/123
HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Content-Length: 0
请求成功的创建了一个新文档,Elasticsearch将返回正常的元数据且响应状态码是201 Created,如果文档已存在,Elasticsearch将返回409 Conflict响应状态码。
解决冲突:
1.在读一行数据前锁定这行,然后确保只有加锁的那个线程可以修改这行数据。
2.在读写过程中数据发生了变化,更新操作将失败。这时候由程序决定在失败后如何解决冲突。实际情况中,可以重新尝试更新,刷新数据(重新读取)或者直接反馈给用户。
如果需要从Elasticsearch中检索多个文档,相对于一个一个的检索,更快的方式是在一个请求中使用multi-get或者mget API。mget是针对读,针对所有主从分片。
POST /_mget
{
"docs" : [
{
"_index" : "website",
"_type" : "blog",
"_id" : 2
},
{
"_index" : "website",
"_type" : "pageviews",
"_id" : 1,
"_source": "views"
}
]
}
bulk API允许我们使用单一请求来实现多个文档的create、index、update或delete。针对主分片操作。
POST /_bulk
{ "create": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "title": "Cannot create - it already exists" }
{ "index": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "title": "But we can update it" }
整个批量请求需要被加载到接受我们请求节点的内存里,所以请求越大,给其它请求可用的内存就越小。有一个最佳的bulk请求大小。超过这个大小,性能不再提升而且可能降低。
路由文档到分片
当你索引一个文档,它被存储在单独一个主分片上。Elasticsearch是如何知道文档属于哪个分片的呢?当你创建一个新文档,它是如何知道是应该存储在分片1还是分片2上的呢?
进程不能是随机的,因为我们将来要检索文档。事实上,它根据一个简单的算法决定:
shard = hash(routing) % number_of_primary_shards
routing值是一个任意字符串,它默认是_id但也可以自定义。这个routing字符串通过哈希函数生成一个数字,然后除以主切片的数量得到一个余数(remainder),余数的范围永远是0到
number_of_primary_shards - 1,这个数字就是特定文档所在的分片。
这也解释了为什么主分片的数量只能在创建索引时定义且不能修改:如果主分片的数量在未来改变了,所有先前的路由值就失效了,文档也就永远找不到了。
replication复制
复制默认的值是sync。这将导致主分片得到复制分片的成功响应后才返回。设置replication为async,请求在主分片上被执行后就会返回给客户端。它依旧会转发请求给复制节点,但将不知道复制
节点成功与否。
consistency
默认主分片在尝试写入时需要规定数量(quorum)或过半的分片(可以是主节点或复制节点)可用。
int( (primary + number_of_replicas) / 2 ) + 1 number_of_replicas是复制分片的数量。
数据检索
1.客户端给Node 1发送get请求。
2.节点使用文档的_id确定文档属于分片0。分片0对应的复制分片在三个节点上都有。负载均衡转发请求到Node 2。
3.Node 2返回文档(document)给Node 1然后返回给客户端。
搜索:
hits:响应中最重要的部分是hits,它包含了total字段来表示匹配到的文档总数,hits数组还包含了匹配到的前10条数据。每个节点都有一个_score字段,这是相关性得分(relevance score),
它衡量了文档与查询的匹配程度。按照_score降序排列的
took告诉我们整个搜索请求花费的毫秒数。
time_out值告诉我们查询超时与否。
{
"hits" : {
"total" : 14,
"hits" : [
{
"_index": "us",
"_type": "tweet",
"_id": "7",
"_score": 1,
"_source": {
"date": "2014-09-17",
"name": "John Smith",
"tweet": "The Query DSL is really powerful and flexible",
"user_id": 2
}
},
... 9 RESULTS REMOVED ...
],
"max_score" : 1
},
"took" : 4,
"_shards" : {
"failed" : 0,
"successful" : 10,
"total" : 10
},
"timed_out" : false
}
多索引和多类别:
GET /_all/tweet/_search?q=tweet:elasticsearch _all:所有文档
/_search
在所有索引的所有类型中搜索
/gb/_search
在索引gb的所有类型中搜索
/gb,us/_search
在索引gb和us的所有类型中搜索
/g*,u*/_search
在以g或u开头的索引的所有类型中搜索
Elasticsearch分页展示,接受from和size参数:
size: 结果数,默认10
from: 跳过开始的结果数,默认0
如果你想每页显示5个结果,页码从1到3,那请求如下:
GET /_search?size=5
GET /_search?size=5&from=5
GET /_search?size=5&from=10
映射(mapping)机制用于进行字段类型确认,将每个字段匹配为一种确定的数据类型(string, number, booleans, date等)。
分析(analysis)机制用于进行全文文本(Full Text)的分词,以建立供搜索用的反向索引。
例:Elasticsearch在对gb索引中的tweet类型进行mapping,Elasticsearch为对字段类型进行猜测,动态生成了字段和类型的映射关系
date类型的字段和string类型的字段的索引方式是不同的,查询匹配日期结果也是不同的。
{
"gb": {
"mappings": {
"tweet": {
"properties": {
"date": {
"type": "date",
"format": "dateOptionalTime"
},
"name": {
"type": "string"
},
"tweet": {
"type": "string"
},
"user_id": {
"type": "long"
}
}
}
}
}
}
Elasticsearch中的数据可以大致分为两种类型:
确切值确定的,正如它的名字一样。比如一个date或用户ID,确切值"Foo"和"foo"就并不相同。确切值2014和2014-09-15也不相同。
全文文本,文本化的数据,全文文本常常被称为非结构化数据,匹配程度查询,例如一封邮件
分析器:
当你查询全文(full text)字段,查询将使用相同的分析器来分析查询字符串,以产生正确的词列表。全文检索需要分词。
当你查询一个确切值(exact value)字段,查询将不分析查询字符串,但是你可以自己指定。确切值查询不需要分词。
Elasticsearch支持以下简单字段类型:
类型 表示的数据类型
String string
Whole number byte, short, integer, long
Floating point float, double
Boolean boolean
Date date
查看映射:
GET /gb/_mapping/tweet
index值 解释
analyzed 首先分析这个字符串,然后索引。换言之,以全文形式索引此字段。
not_analyzed 索引这个字段,使之可以被搜索,但是索引内容和指定值一样。不分析此字段。
no 不索引这个字段。这个字段不能为搜索到。
string类型字段默认值是analyzed。如果我们想映射字段为确切值,我们需要设置它为not_analyzed:
{
"tag": {
"type": "string",
"index": "not_analyzed"
}
}
叶子子句(leaf clauses)(比如match子句)用以在将查询字符串与一个字段(或多字段)进行比较
复合子句(compound)用以合并其他的子句。例如,bool子句允许你合并其他的合法子句,must,must_not或者should,如果可能的话:
{
"bool": {
"must": { "match": { "tweet": "elasticsearch" }},
"must_not": { "match": { "name": "mary" }},
"should": { "match": { "tweet": "full text" }}
}
}
must :: 多个查询条件的完全匹配,相当于 and。
must_not :: 多个查询条件的相反匹配,相当于 not。
should :: 至少有一个查询条件匹配, 相当于 or。
结构化查询(Query DSL)查询语句会询问每个文档的字段值与特定值的匹配程度如何
结构化过滤(Filter DSL)一条过滤语句会询问每个文档的字段值是否包含着特定值
最常用到的查询过滤语句:
term主要用于精确匹配哪些值,比如数字,日期,布尔值或 not_analyzed的字符串(未经分析的文本数据类型)
terms 跟 term 有点类似,但 terms 允许指定多个匹配条件。
range过滤允许我们按照指定范围查找一批数据
范围操作符包含:
gt :: 大于
gte:: 大于等于
lt :: 小于
lte:: 小于等于
exists 和 missing 过滤可以用于查找文档中是否包含指定字段或没有某个字段
validate API 可以验证一条查询语句是否合法。
GET /gb/tweet/_validate/query
{
"query": {
"tweet" : {
"match" : "really powerful"
}
}
}
以上请求的返回值告诉我们这条语句是非法的:
{
"valid" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"failed" : 0
}
}
理解查询语句:使用 explain 参数可以返回一个带有查询语句的可阅读描述
GET /_validate/query?explain
{
"query": {
"match" : {
"tweet" : "really powerful"
}
}
}
explanation 会为每一个索引返回一段描述,因为每个索引会有不同的映射关系和分析器:
{
"valid" : true,
"_shards" : { ... },
"explanations" : [ {
"index" : "us",
"valid" : true,
"explanation" : "tweet:really tweet:powerful"
}, {
"index" : "gb",
"valid" : true,
"explanation" : "tweet:really tweet:power"
} ]
}
【原创】原创文章,更多关注敬请关注微信公众号。