该文章是我读《Elasticsearch权威指南》后的知识总结,学习任何一门技术,读任何一本书都需要总结知识经验,好记性不如烂笔头,初识elasticsearch,如有总结不恰当的地方,还请各路大神不吝赐教。
Elasticsearch 是一个分布式、可扩展、实时的搜索与数据分析引擎。它是全文检索、结构化搜索、分析以及这三个功能的组合。
Elasticsearch 的集群监控信息中包含了许多的统计数据,其中最为重要的一项就是 集群健康 , 它在 status 字段中展示为 green 、 yellow 或者 red。
利用命令:GET /_cluster/health 查看集群健康
通过查看返回结果的status来分析集群的健康
status 字段指示着当前集群在总体上是否工作正常。它的三种颜色含义如下:
green:所有的主分片和副本分片都正常运行。
yellow:所有的主分片都正常运行,但不是所有的副本分片都正常运行。
red:有主分片没能正常运行。
Elasticsearch 添加数据时需要用到 索引 —— 保存相关数据的地方。 索引实际上是指向一个或者多个物理 分片 的 逻辑命名空间。
添加索引命令:PUT 索引名 {数据内容} 例如添加一个blogs的索引
PUT /blogs
{
"settings" : {
"number_of_shards" : 3,
"number_of_replicas" : 1
}
}
文档类似于平时术语中的对象,不过,有一个区别: 一个对象仅仅是类似于 hash 、 hashmap 、字典或者关联数组的 JSON 对象,对象中也可以嵌套其他的对象它是指最顶层或者根对象, Elasticsearch 文档这个术语有特殊的含义,它是指最顶层或者根对象,这个根对象被序列化成 JSON 并存储到 Elasticsearch 中,它指定了唯一 ID。
一个文档不仅仅包含它的数据 ,也包含 元数据 —— 有关 文档的信息。 三个必须的元数据元素如下:
_index
文档在哪存放
_type
文档表示的对象类别
_id
文档唯一标识
通过使用 index API ,文档可以被 索引 —— 存储和使文档可被搜索 。 但是首先,我们要确定文档的位置。一个文档的 _index 、 _type 和 _id 唯一标识一个文档。 我们可以提供自定义的 _id 值,或者让 index API 自动生成。
提供自己的ID:
PUT /{index}/{type}/{id}
{
"field": "value",
...
}
Elasticsearch 自动生成 ID 。
请求的结构调整为: 不再使用 PUT 谓词(“使用这个 URL 存储这个文档”), 而是使用 POST 谓词(“存储文档在这个 URL 命名空间下”)。
POST /website/blog/
{
"title": "My second blog entry",
"text": "Still trying this out...",
"date": "2014/01/01"
}
①:从 Elasticsearch 中检索出文档 ,仍然使用相同的 _index , _type , 和 _id ,但是 HTTP 谓词 更改为 GET :
GET /website/blog/123?pretty –>(id)
②:GET 请求的响应体包括 {“found”: true} ,这证实了文档已经被找到。 如果请求一个不存在的文档,仍旧会得到一个 JSON 响应体,但是 found 将会是 false 。 此外, HTTP 响应码将会是 404 Not Found ,而不是 200 OK 。
③:可以通过传递 -i 参数给 curl 命令,该参数 能够显示响应的头部:
curl -i -XGET http://localhost:9200/website/blog/124?pretty
④:默认情况GET 请求 会返回整个文档,但是也可以通过改变请求url来获取自己感兴趣的部分。如:
GET /website/blog/123?_source=title,text 这个url就会只返回字段title和text的内容。
⑤:如果只想检查一个文档是否存在 –根本不想关心内容–那么用 HEAD 方法来代替 GET 方法。 HEAD 请求没有返回体,只返回一个 HTTP 请求报头:
curl -i -XHEAD http://localhost:9200/website/blog/123
①:从 Elasticsearch 检索很多文档,使用 multi-get 或者 mget API 来将这些检索请求放在一个请求中,将比逐个文档请求更快地检索到全文档。
mget API 要求有一个 docs 数组作为参数,每个 元素包含需要检索文档的元数据, 包括 _index 、 _type 和 _id 。如果你想检索一个或者多个特定的字段,可以通过 _source 参数来指定这些字段的名字:
GET /_mget
{
"docs" : [
{
"_index" : "website",
"_type" : "blog",
"_id" : 2
},
{
"_index" : "website",
"_type" : "pageviews",
"_id" : 1,
"_source": "views"
}
]
}
VIEW IN SENSE
该响应体也包含一个 docs 数组 , 对于每一个在请求中指定的文档,这个数组中都包含有一个对应的响应,且顺序与请求中的顺序相同。 其中的每一个响应都和使用单个 get request 请求所得到的响应体相同:
②:如果所有文档的 _index 和 _type 都是相同的,你可以只传一个 ids 数组,而不是整个 docs 数组:
GET /website/blog/_mget
{
"ids" : [ "2", "1" ]
}
GET /_search
{}
查询表达式(Query DSL)是一种非常灵活又富有表现力的 查询语言。 Elasticsearch 使用它可以以简单的 JSON 接口来展现 Lucene 功能的绝大部分。
查询语句的结构
一个查询语句 的典型结构:
{
QUERY_NAME: {
ARGUMENT: VALUE,
ARGUMENT: VALUE,...
}
}
如果是针对某个字段,那么它的结构如下:
{
QUERY_NAME: {
FIELD_NAME: {
ARGUMENT: VALUE,
ARGUMENT: VALUE,...
}
}
}
举个例子,你可以使用 match 查询语句 来查询 tweet 字段中包含 elasticsearch 的 tweet:
{
"match": {
"tweet": "elasticsearch"
}
}
完整的查询请求如下:
GET /_search
{
"query": {
"match": {
"tweet": "elasticsearch"
}
}
}
查询语句(Query clauses)可以彼此之间合并组成更复杂的查询。这些语句可以是如下形式:
叶子语句(Leaf clauses) (就像 match 语句) 被用于将查询字符串和一个字段(或者多个字段)对比。
复合(Compound) 语句 主要用于 合并其它查询语句。 比如,一个 bool 语句 允许在你需要的时候组合其它语句,无论是 must 匹配、 must_not 匹配还是 should 匹配,同时它可以包含不评分的过滤器(filters):
{
"bool": {
"must": { "match": { "tweet": "elasticsearch" }},
"must_not": { "match": { "name": "mary" }},
"should": { "match": { "tweet": "full text" }},
"filter": { "range": { "age" : { "gt" : 30 }} }
}
}
VIEW IN SENSE
一条复合语句可以合并 任何 其它查询语句,包括复合语句,复合语句之间可以互相嵌套,可以表达非常复杂的逻辑。
例如,以下查询是为了找出信件正文包含 business opportunity 的星标邮件,或者在收件箱正文包含 business opportunity 的非垃圾邮件:
{
"bool": {
"must": { "match": { "email": "business opportunity" }},
"should": [
{ "match": { "starred": true }},
{ "bool": {
"must": { "match": { "folder": "inbox" }},
"must_not": { "match": { "spam": true }}
}}
],
"minimum_should_match": 1
}
}
match_all 查询
match_all 查询简单的 匹配所有文档。在没有指定查询方式时,它是默认的查询:
{ "match_all": {}}
VIEW IN SENSE
它经常与 filter 结合使用--例如,检索收件箱里的所有邮件。所有邮件被认为具有相同的相关性,所以都将获得分值为 1 的中性 `_score`。
match 查询
无论你在任何字段上进行的是全文搜索还是精确查询,match 查询是你可用的标准查询。
如果你在一个全文字段上使用 match 查询,在执行查询前,它将用正确的分析器去分析查询字符串:
{ "match": { "tweet": "About Search" }}
VIEW IN SENSE
如果在一个精确值的字段上使用它, 例如数字、日期、布尔或者一个 not_analyzed 字符串字段,那么它将会精确匹配给定的值:
{ "match": { "age": 26 }}
{ "match": { "date": "2014-09-01" }}
{ "match": { "public": true }}
{ "match": { "tag": "full_text" }}
VIEW IN SENSE
Tip
对于精确值的查询,你可能需要使用 filter 语句来取代 query,因为 filter 将会被缓存。下面是一些关于 filter 的例子。
不像字符串查询(query-string search), match 查询不使用类似 +user_id:2 +tweet:search 的查询语法。它只是去查找给定的单词。这就意味着将查询字段暴露给用户是安全的;你需要控制那些允许被查询字段,不易于抛出语法异常。
multi_match 查询
multi_match 查询可以在多个字段上执行相同的 match 查询:
{
"multi_match": {
"query": "full text search",
"fields": [ "title", "body" ]
}
}
VIEW IN SENSE
range 查询
range 查询找出那些落在指定区间内的数字或者时间:
{
"range": {
"age": {
"gte": 20,
"lt": 30
}
}
}
VIEW IN SENSE
被允许的操作符如下:
gt
大于
gte
大于等于
lt
小于
lte
小于等于
term 查询
term 查询被用于精确值 匹配,这些精确值可能是数字、时间、布尔或者那些 not_analyzed 的字符串:
{ "term": { "age": 26 }}
{ "term": { "date": "2014-09-01" }}
{ "term": { "public": true }}
{ "term": { "tag": "full_text" }}
VIEW IN SENSE
term 查询对于输入的文本不 分析 ,所以它将给定的值进行精确查询。
terms 查询
terms 查询和 term 查询一样,但它允许你指定多值进行匹配。如果这个字段包含了指定值中的任何一个值,那么这个文档满足条件:
{ "terms": { "tag": [ "search", "full_text", "nosql" ] }}
VIEW IN SENSE
和 term 查询一样,terms 查询对于输入的文本不分析。它查询那些精确匹配的值(包括在大小写、重音、空格等方面的差异)。
exists 查询和 missing 查询
exists 查询和 missing 查询被用于查找那些指定字段中有值 (exists) 或无值 (missing) 的文档。这与SQL中的 IS_NULL (missing) 和 NOT IS_NULL (exists) 在本质上具有共性:
{
"exists": {
"field": "title"
}
}
在 Elasticsearch 中文档是 不可改变 的,不能修改它们。 如果想要更新现有的文档,需要 重建索引 或者进行替换, 我们可以使用相同的 index API 进行实现。
例如:
PUT /website/blog/123
{
"title": "My first blog entry",
"text": "I am starting to get the hang of this...",
"date": "2014/01/02"
}
在响应体中,能看到 Elasticsearch 已经增加了 _version 字段值,在内部,Elasticsearch 已将旧文档标记为已删除,并增加一个全新的文档。 尽管你不能再对旧版本的文档进行访问,但它并不会立即消失。当继续索引更多的数据,Elasticsearch 会在后台清理这些已删除文档。
可以在 update API中用来改变 _source 的字段内容, 它在更新脚本中称为 ctx._source 。 例如,我们可以使用脚本来增加博客文章中 views 的数量:
POST /website/blog/1/_update
{
"script" : "ctx._source.views+=1"
}
删除文档 的语法和上述规则相同,只是 使用 DELETE 方法:
DELETE /website/blog/123
如果文档没有 找到将得到 404 Not Found 的响应码和类似这样的响应体: