ElasticSearch学习二-文档与搜索

1. 文档

在 Elasticsearch 中,每一个字段的全部数据都是默认被索引的。html

大多数实体和对象均可以被序列化为包含键值对的JSON对象,JSON对象能表示字符串、数字、布尔值、甚至另外一个对象。以下所示:web

{
    "name":         "John Smith",
    "age":          42,
    "confirmed":    true,
    "join_date":    "2014-06-01",
    "home": {
        "lat":      51.5,
        "lon":      0.1
    },
    "accounts": [
        {
            "type": "facebook",
            "id":   "johnsmith"
        },
        {
            "type": "twitter",
            "id":   "johnsmith"
        }
    ]
}
复制代码

文档的定义:它是指最顶层或者根对象, 这个根对象被序列化成 JSON 并存储到 Elasticsearch 中,指定了惟一 ID。数据库

1.1 文档的元数据

元数据 —— 有关文档的信息,与文档包含的数据相区分。json

有以下三个元数据:数组

  1. _index:文档存放在哪网络

    一个索引应该是因共同的特性被分组到一块儿的文档集合,如可能存储全部的产品在索引 products 中。索引名必须小写,不能如下划线开头,不能包含逗号。并发

  2. _type:文档的类型elasticsearch

    Elasticsearch 公开了一个称为 types (类型)的特性,它容许您在索引中对数据进行逻辑分区。不一样 types 的文档可能有不一样的字段,但最好可以很是类似。至关于在_index下继续细分。ide

  3. _id:文档的惟一标识post

    ID 是一个字符串, 当它和 _index 以及 _type 组合就能够惟一肯定 Elasticsearch 中的一个文档。

1.2 储存文档

如何肯定一个文档的位置呢?就如上面所说的,三个元数据肯定一个文档。如储存一个文档:

PUT /{index}/{type}/{id}
{
  "field": "value",
  ...
}
复制代码

如何像数据库自增主键那样由ElasticSearch提供id呢,使用POST谓词就能够了。

POST /website/blog/
{
  "title": "My second blog entry",
  "text":  "Still trying this out...",
  "date":  "2014/01/01"
}
复制代码

会自动生成一个基于 Base64 编码且长度为 20 个字符的 GUID 字符串

1.3 取回文档

一样的只须要把谓词改成GET,同时提供三个元数据就能够了:

GET /website/blog/123?pretty
复制代码

加上pretty参数使得 JSON 响应体更加可读。若是只想返回文档的一部分则在url上添加_source指定想要的字段就好了。

1.4 更新整个文档

在 Elasticsearch 中文档是不可改变的,不能修改它们,只能进行替换。至关于使用PUT再从新将整个文档PUT一下,Elasticsearch将旧文档标记为已删除,并增长一个全新的文档。

(建立和删除文档略)

1.5 部分更新文档

使用 update API能够部分更新文档,例如在某个请求时对计数器进行累加。对象被合并到一块儿,覆盖现有的字段,增长新的字段。如:

POST /website/blog/1/_update
{
   "doc" : {
      "tags" : [ "testing" ],
      "views": 0
   }
}
复制代码

在文档中增长了tags和views字段。

也可使用脚本和参数更新:

POST /website/blog/1/_update
{
   "script" : "ctx._source.tags+=new_tag",
   "params" : {
      "new_tag" : "search"
   }
}
复制代码

为了不数据丢失, update API 在检索步骤时检索获得文档当前的 _version 号,并传递版本号到重建索引步骤的 index 请求。 若是另外一个进程修改了处于检索和从新索引步骤之间的文档,那么 _version 号将不匹配,更新请求将会失败。

还能够在url后加上retry_on_conflict=5参数,表示失败以前重试5次。

1.6 乐观并发控制

ElasticSearch使用乐观并发控制,每一个文档都有一个版本号_version,当文档被修改时版本号递增。 Elasticsearch 使用这个 _version 号来确保变动以正确顺序获得执行。咱们经过指定想要修改文档的 version 号来达到这个目的,若是该版本不是当前版本号,咱们的请求将会失败(也就是一次Compare And Set)。

1.7 批量取回多个文档

使用mget API来取回多个文档能够减小网络流量,参数在请求体里的docs数组中提供:

GET /_mget
{
   "docs" : [
      {
         "_index" : "website",
         "_type" :  "blog",
         "_id" :    2
      },
      {
         "_index" : "website",
         "_type" :  "pageviews",
         "_id" :    1,
         "_source": "views"
      }
   ]
}
复制代码

还有其余的批量查询方法能够查看官方文档

返回文档顺序和请求的一致。

1.8 批量操做

很简单一看就懂,使用bulk API,主要就是语法的问题,不太好掌握。

POST /_bulk
{ "delete": { "_index": "website", "_type": "blog", "_id": "123" }} 
{ "create": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "title":    "My first blog post" }
{ "index":  { "_index": "website", "_type": "blog" }}
{ "title":    "My second blog post" }
{ "update": { "_index": "website", "_type": "blog", "_id": "123", "_retry_on_conflict" : 3} }
{ "doc" : {"title" : "My updated blog post"} } 
复制代码

2. 搜索

2.1 空搜索

什么条件也不附加的空搜索,搜索ElasticSearch中的全部文档:

GET /_search
复制代码

返回全部查询结果的前十个文档而不是只是返回id。

2.2 指定index,type搜索

前面的空搜索是搜索全部文档,若是要想指定元数据搜索怎么办呢?很好办,在url中指明便可:

/gb/_search

gb 索引中搜索全部的类型

/gb,us/_search

gbus 索引中搜索全部的文档

/g*,u*/_search

在任何以 g 或者 u 开头的索引中搜索全部的类型

/gb/user/_search

gb 索引中搜索 user 类型

/gb,us/user,tweet/_search

gbus 索引中搜索 usertweet 类型

/_all/user,tweet/_search

在全部的索引中搜索 usertweet 类型

2.3 分页

和传统的数据库同样,ElasticSearch也有分页的功能,使用from 和 size 参数:

size

显示应该返回的结果数量,默认是 10

from

显示应该跳过的初始结果数量,默认是 0

GET /_search?size=5&from=10
复制代码

2.4 轻量级搜索

以前咱们看到的搜索都是有个JSON请求体,可是还有一种更简便的轻量级搜索方式.

  1. 搜索全部包含关键字的文档:

    GET /_search?q=mary
    复制代码
  2. 搜索包含关键字的全部文档:

    GET /_search?q=mary
    复制代码
  3. 指定匹配多个关键字的文档:

    GET /_search?q=+name:john +tweet:mary
    复制代码

    + 前缀表示必须与查询条件匹配。相似地, - 前缀表示必定不与查询条件匹配。

    注意+、-、:都要使用URL编码,实际上上面的查询语句应该是:

    GET /_search?q=%2Bname%3Ajohn+%2Btweet%3Amary
    复制代码

那么ElasticSearch如何从JSON的不一样字段搜索关键字呢?原来ElasticSearch在储存一个文档上,会将该JSON全部字段提取出来拼接成一个字符串,而后增长一个_all字段,将该字符串添加到all字段上。

3. 请求体查询

请求体查询就像是一个带请求体的GET请求:

GET /_search
{
  "from": 30,
  "size": 10
}
复制代码

3.1 查询表达式

Elasticsearch 使用查询表达式能够以简单的 JSON 接口来编写查询语句。只须要将语句传递给query参数就能够了。如查询 tweet 字段中包含 elasticsearch 的 tweet:

GET /_search
{
    "query": {
        "match": {
            "tweet": "elasticsearch"
        }
    }
}
复制代码

当你有多个查询条件是能够合并查询语句:

{
    "bool": {
        "must":     { "match": { "tweet": "elasticsearch" }},
        "must_not": { "match": { "name":  "mary" }},
        "should":   { "match": { "tweet": "full text" }},
        "filter":   { "range": { "age" : { "gt" : 30 }} }
    }
}
复制代码

3.2 重要的查询

  1. 默认查询match_all匹配全部文档:
{ "match_all": {}}
复制代码
  1. 标准查询match,可用于全文搜索和精确查询:
{ "match": { "age":    26           }}
{ "match": { "date":   "2014-09-01" }}
{ "match": { "public": true         }}
{ "match": { "tag":    "full_text"  }}
复制代码
  1. mulit_match查询,能够在多个字段上执行相同的 match 查询:
{
    "multi_match": {
        "query":    "full text search",
        "fields":   [ "title", "body" ]
    }
}
复制代码
  1. range查询,有gt,gte,lt,lte字段:
{
    "range": {
        "age": {
            "gte":  20,
            "lt":   30
        }
    }
}
复制代码
  1. term查询用于精确匹配,不对查询字符串作分析处理
{ "term": { "age":    26           }}
{ "term": { "date":   "2014-09-01" }}
{ "term": { "public": true         }}
{ "term": { "tag":    "full_text"  }}
复制代码

3.3 组合多查询

若是想在多个字段上查询多种多样的文本怎么办呢?可使用bool 查询来实现你的需求。bool 查询接收如下参数:

must

文档 必须 匹配这些条件才能被包含进来。

must_not

文档 必须不 匹配这些条件才能被包含进来。

should

若是知足这些语句中的任意语句,将增长 _score ,不然,无任何影响。它们主要用于修正每一个文档的相关性得分。

filter

必须 匹配,但它以不评分、过滤模式来进行。这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档。

以下面这个查询的意思是必须知足title 字段匹配 how to make millions而且不被标识为 spam 的文档。若是是starred且在2014年后的邮件会有更高的排名:

"bool": {
        "must":     { "match": { "title": "how to make millions" }},
        "must_not": { "match": { "tag":   "spam" }},
        "should": [
            { "match": { "tag": "starred" }},
            { "range": { "date": { "gte": "2014-01-01" }}}
        ]
    }
复制代码

每个子查询都独自地计算文档的相关性得分。一旦他们的得分被计算出来, bool 查询就将这些得分进行合并而且返回一个表明整个布尔操做的得分。

bool查询默认是评分的,将 bool 查询包裹在 filter 语句中,就能够在过滤标准中增长布尔逻辑。

相关文章
相关标签/搜索