索引文档

通过使用 index API ,文档可以被 索引 —— 存储和使文档可被搜索 。 但是首先,我们要确定文档的位置。正如我们刚刚讨论的,一个文档的 _index 、 _type 和 _id 唯一标识一个文档。 我们可以提供自定义的 _id 值,或者让 index API 自动生成。

创建新文档

当我们索引一个文档, 怎么确认我们正在创建一个完全新的文档,而不是覆盖现有的呢?

请记住, _index 、 _type 和 _id 的组合可以唯一标识一个文档。所以,确保创建一个新文档的最简单办法是,使用索引请求的 POST 形式让 Elasticsearch 自动生成唯一 _id :

POST /website/blog/
{ ... }

然而,如果已经有自己的 _id ,那么我们必须告诉 Elasticsearch ,只有在相同的 _index 、 _type 和 _id 不存在时才接受我们的索引请求。这里有两种方式,他们做的实际是相同的事情。使用哪种,取决于哪种使用起来更方便。

第一种方法使用 op_type 查询 -字符串参数:

PUT /website/blog/123?op_type=create
{ ... }

第二种方法是在 URL 末端使用 /_create :

PUT /website/blog/123/_create
{ ... }

如果创建新文档的请求成功执行,Elasticsearch 会返回元数据和一个 201 Created 的 HTTP 响应码。

另一方面,如果具有相同的 _index 、 _type 和 _id 的文档已经存在,Elasticsearch 将会返回 409 Conflict 响应码,以及如下的错误信息:

{
"error": {
"root_cause": [
{
"type": "document_already_exists_exception",
"reason": "[blog][123]: document already exists",
"shard": "0",
"index": "website"
}
],
"type": "document_already_exists_exception",
"reason": "[blog][123]: document already exists",
"shard": "0",
"index": "website"
},
"status": 409
}

使用自定义的 ID

如果你的文档有一个自然的 标识符 (例如,一个 user_account 字段或其他标识文档的值),你应该使用如下方式的 index API 并提供你自己 _id :

PUT /{index}/{type}/{id}
{
"field": "value",
...
}

举个例子,如果我们的索引称为 website ,类型称为 blog ,并且选择 123 作为 ID ,那么索引请求应该是下面这样:

PUT /website/blog/123
{
"title": "My first blog entry",
"text": "Just trying this out...",
"date": "2014/01/01"
}

Elasticsearch 响应体如下所示:

{

       "_index":    "website",

       "_type":     "blog",

       "_id":       "123",

       "_version":  1,

       "created":   true

    }

该响应表明文档已经成功创建,该索引包括 _index 、 _type 和 _id 元数据, 以及一个新元素: _version 。

在 Elasticsearch 中每个文档都有一个版本号。当每次对文档进行修改时(包括删除), _version 的值会递增。 在 处理冲突 中,我们讨论了怎样使用 _version 号码确保你的应用程序中的一部分修改不会覆盖另一部分所做的修改。

Autogenerating IDs

如果你的数据没有自然的 ID, Elasticsearch 可以帮我们自动生成 ID 。 请求的结构调整为: 不再使用PUT 谓词(“使用这个 URL 存储这个文档”), 而是使用 POST 谓词(“存储文档在这个 URL 命名空间下”)。

现在该 URL 只需包含 _index 和 _type :

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

除了 _id 是 Elasticsearch 自动生成的,响应的其他部分和前面的类似:

{

       "_index":    "website",

       "_type":     "blog",

       "_id":       "AVFgSgVHUP18jI2wRx0w",

       "_version":  1,

       "created":   true

    }

自动生成的 ID 是 URL-safe、 基于 Base64 编码且长度为20个字符的 GUID 字符串。 这些 GUID 字符串由可修改的 FlakeID 模式生成,这种模式允许多个节点并行生成唯一 ID ,且互相之间的冲突概率几乎为零

路由

路由的默认原则

保存文档时,文档会通过一个公式路由到一个索引中的一个分片上。默认的公式如下:

shard_num = hash(_routing) % num_primary_shards

默认情况下时通过_routing字段进行路由的,这个字段的值默认时等于文档_id字段的。

自定义路由

PUT my_index/my_type/1?routing=user1&refresh=true
{
"title": "This is a document"
} GET my_index/my_type/1?routing=user1

上面的代码中,指定了一个用户属性作为路由进行分区,然后查询的时候也必须指定路由。这一点需要注意 只要在索引时候加入路由字段,那么在以后的get,delete,update操作中都必须使用路由字段,否则会出现问题。

当然,路由字段本身,也是可以被查询的,看下面的代码:

GET my_index/_search
{
"query": {
"terms": {
"_routing": [ "user1" ]
}
}
}

除此之外,路由字段,也可以指定多个:

GET my_index/_search?routing=user1,user2
{
"query": {
"match": {
"title": "document"
}
}
}

如果指定多个用户属性,那么es会仅仅查询关联了这两个route属性的shard

如果加入路由字段之后,其他的操作(indexing,getting,deleting,updating)都必须指定路由字段,为了避免在使用时忘记添加 路由字段,导致同类数据会分布在多个shard上,这就违反了路由的原则,所以我们可以在mapping中 设置路由字段是必须字段,否则会提示错误:

PUT my_index2
{
"mappings": {
"my_type": {
"_routing": {
"required": true
}
}
}
} PUT my_index2/my_type/1
{
"text": "No routing value provided"
}

缺失路由字段会抛出异常:

routing_missing_exception

还需要注意到是如果使用了路由字段,那么_id字段只能由用户保证唯一性,因为同一个id的数据,如果路由字段不一样 它是可以被存在到多个shard中的,而默认情况下是不会出现这种情况的。

Timeout

执行索引操作时,分配用于执行索引操作的主分片可能不可用。原因可能是主分片当前正在从正在进行重定位的网关中恢复。默认情况下,索引操作将在主分片上等待最多1分钟,然后才会出现故障并响应错误。 thetimeout参数可用于明确指定等待的时间。以下是将其设置为5分钟的示例:

PUT twitter/_doc/1?timeout=5m
{"user":"kimchy","post_date":"2009-11-15T14:12:12","message":"trying out Elasticsearch"}

更新整个文档

在 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 字段值:

{

      "_index" :   "website",

      "_type" :    "blog",

      "_id" :      "123",

      "_version" : 2,

      "created":   false  

    }

 created 标志设置成 false ,是因为相同的索引、类型和 ID 的文档已经存在。

在内部,Elasticsearch 已将旧文档标记为已删除,并增加一个全新的文档。 尽管你不能再对旧版本的文档进行访问,但它并不会立即消失。当继续索引更多的数据,Elasticsearch 会在后台清理这些已删除文档。

在本章的后面部分,我们会介绍 update API, 这个 API 可以用于 partial updates to a document 。 虽然它似乎对文档直接进行了修改,但实际上 Elasticsearch 按前述完全相同方式执行以下过程:

  1. 从旧文档构建 JSON
  2. 更改该 JSON
  3. 删除旧文档
  4. 索引一个新文档

唯一的区别在于, update API 仅仅通过一个客户端请求来实现这些步骤,而不需要单独的 get 和 index 请求。

文档的部分更新

在 更新整个文档 , 我们已经介绍过 更新一个文档的方法是检索并修改它,然后重新索引整个文档,这的确如此。然而,使用 update API 我们还可以部分更新文档,例如在某个请求时对计数器进行累加。

我们也介绍过文档是不可变的:他们不能被修改,只能被替换。 update API 必须遵循同样的规则。 从外部来看,我们在一个文档的某个位置进行部分更新。然而在内部, update API 简单使用与之前描述相同的 检索-修改-重建索引 的处理过程。 区别在于这个过程发生在分片内部,这样就避免了多次请求的网络开销。通过减少检索和重建索引步骤之间的时间,我们也减少了其他进程的变更带来冲突的可能性。

update 请求最简单的一种形式是接收文档的一部分作为 doc 的参数, 它只是与现有的文档进行合并。对象被合并到一起,覆盖现有的字段,增加新的字段。 例如,我们增加字段 tags 和 views 到我们的博客文章,如下所示:

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

如果请求成功,我们看到类似于 index 请求的响应:

{

       "_index" :   "website",

       "_id" :      "1",

       "_type" :    "blog",

       "_version" : 3

    }

检索文档显示了更新后的 _source 字段:

{

       "_index":    "website",

       "_type":     "blog",

       "_id":       "1",

       "_version":  3,

       "found":     true,

       "_source": {

          "title":  "My first blog entry",

          "text":   "Starting to get the hang of this...",

          "tags": [ "testing" ],  

          "views":  0  

       }

    }

   新的字段已被添加到 _source 中

elasticsearch 基础 —— 索引、更新文档的更多相关文章

  1. Elasticsearch (1) - 索引库 文档 分词

    创建索引库 ES的索引库是一个逻辑概念,它包括了分词列表及文档列表,同一个索引库中存储了相同类型的文档.它就相当于MySQL中的表,或相当于Mongodb中的集合. 关于索引这个语: 索引(名词):E ...

  2. Elasticsearch 7.x 之文档、索引和 REST API 【基础入门篇】

    前几天写过一篇<Elasticsearch 7.x 最详细安装及配置>,今天继续最新版基础入门内容.这一篇简单总结了 Elasticsearch 7.x 之文档.索引和 REST API. ...

  3. ES4:ElasticSearch 使用C#添加和更新文档

    这是ElasticSearch 2.4 版本系列的第四篇: 第一篇:ES1:Windows下安装ElasticSearch 第二篇:ES2:ElasticSearch 集群配置 第三篇:ES3:Ela ...

  4. ElasticSearch入门 第四篇:使用C#添加和更新文档

    这是ElasticSearch 2.4 版本系列的第四篇: ElasticSearch入门 第一篇:Windows下安装ElasticSearch ElasticSearch入门 第二篇:集群配置 E ...

  5. Elasticsearch 更新文档

    章节 Elasticsearch 基本概念 Elasticsearch 安装 Elasticsearch 使用集群 Elasticsearch 健康检查 Elasticsearch 列出索引 Elas ...

  6. elasticsearch查询篇索引映射文档数据准备

    elasticsearch查询篇索引映射文档数据准备 我们后面要讲elasticsearch查询,先来准备下索引,映射以及文档: 我们先用Head插件建立索引film,然后建立映射 POST http ...

  7. Elastic Stack 笔记(四)Elasticsearch5.6 索引及文档管理

    博客地址:http://www.moonxy.com 一.前言 在 Elasticsearch 中,对文档进行索引等操作时,既可以通过 RESTful 接口进行操作,也可以通过 Java 也可以通过 ...

  8. ES使用C#添加和更新文档

    ElasticSearch 使用C#添加和更新文档 这是ElasticSearch 2.4 版本系列的第四篇: 第一篇:ES1:Windows下安装ElasticSearch 第二篇:ES2:Elas ...

  9. elasticsearch的索引操作和文档操作总结

    参考文档:https://es.xiaoleilu.com/010_Intro/00_README.html 一.索引操作 1.查看当前节点的所有的index 查看当前节点的所有的index [roo ...

随机推荐

  1. Could not resolve all files for configuration ':app:debugCompileClasspath'.解决方案

    异常如下: Error:FAILURE: Build failed with an exception. * What went wrong:Could not resolve all files f ...

  2. 【Kickstart】2018 Round (Practice ~ C)

    Practice Round Problem A GBus count (9pt/15pt) (2019年1月14日,kickstart群每日一题) 题意:有一条笔直的大路,上面有城市编号从 1 开始 ...

  3. join优化

    1.left outer join先执行连接操作,再将结果通过WHERE语句进行过滤 select s.ymd,s.symbol,s.price_close,d.dividend from stock ...

  4. hdu 6053: TrickGCD (2017 多校第二场 1009) 【莫比乌斯 容斥原理】

    题目链接 定义f[n]表示n是最大公约数情况下的计数,F[n]为n是公约数情况下的计数 (可以和 http://www.cnblogs.com/Just--Do--It/p/7197788.html  ...

  5. 正则化的L1范数和L2范数

    范数介绍:https://www.zhihu.com/question/20473040?utm_campaign=rss&utm_medium=rss&utm_source=rss& ...

  6. 英语单词independent

    来源——https://www.docker.com/products/docker-hub 回到顶部 Share and Collaborate with Docker Hub Docker Hub ...

  7. Nginx负载均衡与反向代理—《亿级流量网站架构核心技术》

    当我们的应用单实例不能支撑用户请求时,此时就需要扩容,从一台服务器扩容到两台.几十台.几百台.然而,用户访问时是通过如http://www.XX.com的方式访问,在请求时,浏览器首先会查询DNS服务 ...

  8. 写一个简单易用可扩展vue表单验证插件(vue-validate-easy)

    写一个vue表单验证插件(vue-validate-easy) 需求 目标:简单易用可扩展 如何简单 开发者要做的 写了一个表单,指定一个name,指定其验证规则. 调用提交表单方法,可以获取验证成功 ...

  9. scrapy xpath xpath('---').xpath('string(.)') 提取子元素全部文本

    product.xpath("div//div[@class='a-row a-spacing-mini'][1]/div[2]").xpath('string(.)')

  10. 使用 wx.navigateBack返回页面并携带参数的处理方式

    getAddressList (){ let that = this; util.request(api.AddressList).then(function (res) { if (res.errn ...