精华内容
下载资源
问答
  • 最近的索引请求将获胜:无论最后一个文档被索引,都将被唯一存储在 Elasticsearch 中。如果其他人同时更改这个文档,他们的更改将丢失。 很多时候这是没有问题的。也许我们的主数据存储是一个关系型数据库,我们...

    1.数据冲突

    当我们使用 index API 更新文档 ,可以一次性读取原始文档,做我们的修改,然后重新索引 整个文档 。 最近的索引请求将获胜:无论最后哪一个文档被索引,都将被唯一存储在 Elasticsearch 中。如果其他人同时更改这个文档,他们的更改将丢失。

    很多时候这是没有问题的。也许我们的主数据存储是一个关系型数据库,我们只是将数据复制到 Elasticsearch 中并使其可被搜索。 也许两个人同时更改相同的文档的几率很小。或者对于我们的业务来说偶尔丢失更改并不是很严重的问题。

    但有时丢失了一个变更就是 非常严重的 。试想我们使用 Elasticsearch 存储我们网上商城商品库存的数量, 每次我们卖一个商品的时候,我们在 Elasticsearch 中将库存数量减少。

    有一天,管理层决定做一次促销。突然地,我们一秒要卖好几个商品。 假设有两个 web 程序并行运行,每一个都同时处理所有商品的销售,如图所示:
    在这里插入图片描述

    web_1 对 stock_count 所做的更改已经丢失,因为 web_2 不知道它的 stock_count 的拷贝已经过期。 结果会有超过商品的实际数量的库存,但实际卖给顾客的库存商品并不存在;
    变更越频繁,读数据和更新数据的间隙越长,也就越可能丢失变更。
    在数据库领域中,有两种方法通常被用来确保并发更新时变更不会丢失:

    • 悲观并发控制
      这种方法被关系型数据库广泛使用,它假定有变更冲突可能发生,因此阻塞访问资源以防止冲突。 一个典型的例子是读取一行数据之前先将其锁住,确保只有放置锁的线程能够对这行数据进行修改。
    • 乐观并发控制
      Elasticsearch 中使用的这种方法假定冲突是不可能发生的,并且不会阻塞正在尝试的操作。 然而,如果源数据在读写当中被修改,更新将会失败。应用程序接下来将决定该如何解决冲突。 例如,可以重试更新、使用新的数据、或者将相关情况报告给用户。

    2.乐观并发控制

    Elasticsearch 是分布式的。当文档创建、更新或删除时, 新版本的文档必须复制到集群中的其他节点。Elasticsearch 也是异步和并发的,这意味着这些复制请求被并行发送,并且到达目的地时也许 顺序是乱的 。 Elasticsearch 需要一种方法确保文档的旧版本不会覆盖新的版本。

    当我们讨论 index , GET 和 delete 请求时,我们指出每个文档都有一个 _version (版本)号,当文档被修改时版本号递增。 Elasticsearch 使用这个 _version 号来确保变更以正确顺序得到执行。如果旧版本的文档在新版本之后到达,它可以被简单的忽略。

    我们可以利用 _version 号来确保 应用中相互冲突的变更不会导致数据丢失。我们通过指定想要修改文档的 version 号来达到这个目的。 如果该版本不是当前版本号,我们的请求将会失败。
    举例创建一个新的博客文章:

    PUT /website/blog/1/_create
    {
      "title": "My first blog entry",
      "text":  "Just trying this out..."
    }
    

    响应体告诉我们,这个新创建的文档 _version 版本号是 1 。现在假设我们想编辑这个文档:我们加载其数据到 web 表单中, 做一些修改,然后保存新的版本。
    首先我们检索文档:

    GET /website/blog/1
    
    {
      "_index" :   "website",
      "_type" :    "blog",
      "_id" :      "1",
      "_version" : 1,   //响应体包含相同的_version 版本号 1
      "found" :    true,
      "_source" :  {
          "title": "My first blog entry",
          "text":  "Just trying this out..."
      }
    }
    

    现在,当我们尝试通过重建文档的索引来保存修改,我们指定 version 为我们的修改会被应用的版本:

    PUT /website/blog/1?version=1   //只有现在的_version为1时,本次更新才能成功。
    {
      "title": "My first blog entry",
      "text":  "Starting to get the hang of this..."
    }
    

    此请求成功,查看响应体, _version 已经递增到 2

    {
      "_index":   "website",
      "_type":    "blog",
      "_id":      "1",
      "_version": 2
      "created":  false
    }
    

    然而,如果我们重新运行相同的索引请求,仍然指定 version=1 , Elasticsearch 返回 409 Conflict HTTP 响应码,和一个如下所示的响应体:

    {
       "error": {
          "root_cause": [
             {
                "type": "version_conflict_engine_exception",
                "reason": "[blog][1]: version conflict, current [2], provided [1]",
                "index": "website",
                "shard": "3"
             }
          ],
          "type": "version_conflict_engine_exception",
          "reason": "[blog][1]: version conflict, current [2], provided [1]",
          "index": "website",
          "shard": "3"
       },
       "status": 409
    }
    

    结论:以上告诉我们在 Elasticsearch 中这个文档的当前 _version 号是 2 ,但我们指定的更新版本号为 1 。
    我们现在怎么做取决于我们的应用需求。我们可以告诉用户说其他人已经修改了文档,并且在再次保存之前检查这些修改内容。 或者,在之前的商品 stock_count 场景,我们可以获取到最新的文档并尝试重新应用这些修改。
    所有文档的更新或删除 API,都可以接受 version 参数,这允许你在代码中使用乐观的并发控制,这是一种明智的做法。

    3.通过外部系统使用版本控制

    一个常见的设置是使用其它数据库作为主要的数据存储,使用 Elasticsearch 做数据检索, 这意味着主数据库的所有更改发生时都需要被复制到 Elasticsearch ,如果多个进程负责这一数据同步,你可能遇到类似于之前描述的并发问题。

    如果你的主数据库已经有了版本号 ,或一个能作为版本号的字段值比如 timestamp,那么你就可以在 Elasticsearch 中通过增加 version_type=external 到查询字符串的方式重用这些相同的版本号, 版本号必须是大于零的整数, 且小于 9.2E+18 :一个 Java 中 long 类型的正值。

    外部版本号的处理方式和我们之前讨论的内部版本号的处理方式有些不同, Elasticsearch 不是检查当前 _version 和请求中指定的版本号是否相同, 而是检查当前 _version 是否 小于 指定的版本号。 如果请求成功,外部的版本号作为文档的新 _version 进行存储。

    外部版本号不仅在索引和删除请求是可以指定,而且在 创建 新文档时也可以指定。

    例如,要创建一个新的具有外部版本号 6 的博客文章,我们可以按以下方法进行:

    PUT /website/blog/2?version=6&version_type=external
    {
      "title": "My first external blog entry",
      "text":  "Starting to get the hang of this..."
    }
    

    在响应中,我们能看到当前的 _version 版本号是 6 :

    {
      "_index":   "website",
      "_type":    "blog",
      "_id":      "2",
      "_version": 6,
      "created":  true
    }
    

    现在我们更新这个文档,指定一个新的 version 号是 10 :

    PUT /website/blog/2?version=10&version_type=external
    {
      "title": "My first external blog entry",
      "text":  "This is a piece of cake..."
    }
    

    请求成功并将当前 _version 设为 10 :

    {
      "_index":   "website",
      "_type":    "blog",
      "_id":      "2",
      "_version": 10,
      "created":  false
    }
    

    如果你要重新运行此请求时,它将会失败,并返回像我们之前看到的同样的冲突错误, 因为指定的外部版本号不大于 Elasticsearch 的当前版本号。

    展开全文
  • 1.文档元数据 一个文档不仅仅包含它的数据 ,也包含 元数据 ——有关文档的信息,三个必须的元数据元素如下: _index 文档在哪存放 _type ...实际上,在 Elasticsearch 中,我们的数据是被存储和索引在

    1.文档元数据

    一个文档不仅仅包含它的数据 ,也包含 元数据 ——有关文档的信息,三个必须的元数据元素如下:

    • _index
      文档在哪存放
    • _type
      文档表示的对象类别
    • _id
      文档唯一标识

    _index
    一个 索引 应该是因共同的特性被分组到一起的文档集合。 例如,你可能存储所有的产品在索引 products 中,而存储所有销售的交易到索引 sales 中。 虽然也允许存储不相关的数据到一个索引中,但这通常看作是一个反模式的做法。

    实际上,在 Elasticsearch 中,我们的数据是被存储和索引在 分片 中,而一个索引仅仅是逻辑上的命名空间, 这个命名空间由一个或者多个分片组合在一起。 然而,这是一个内部细节,我们的应用程序根本不应该关心分片,对于应用程序而言,只需知道文档位于一个 索引 内。 Elasticsearch 会处理所有的细节。

    我们将在 索引管理 介绍如何自行创建和管理索引,但现在我们将让 Elasticsearch 帮我们创建索引。 所有需要我们做的就是选择一个索引名,这个名字必须小写,不能以下划线开头,不能包含逗号。我们用 website 作为索引名举例。

    _type
    数据可能在索引中只是松散的组合在一起,但是通常明确定义一些数据中的子分区是很有用的。 例如,所有的产品都放在一个索引中,但是你有许多不同的产品类别,比如 “electronics” 、 “kitchen” 和 “lawn-care”。

    这些文档共享一种相同的(或非常相似)的模式:他们有一个标题、描述、产品代码和价格。他们只是正好属于“产品”下的一些子类。

    Elasticsearch 公开了一个称为 types (类型)的特性,它允许您在索引中对数据进行逻辑分区。不同 types 的文档可能有不同的字段,但最好能够非常相似。 我们将在 类型和映射 中更多的讨论关于 types 的一些应用和限制。

    一个 _type 命名可以是大写或者小写,但是不能以下划线或者句号开头,不应该包含逗号, 并且长度限制为256个字符. 我们使用 blog 作为类型名举例。

    _id
    ID 是一个字符串,当它和 _index 以及 _type 组合就可以唯一确定 Elasticsearch 中的一个文档。 当你创建一个新的文档,要么提供自己的 _id ,要么让 Elasticsearch 帮你生成。

    2.索引文档

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

    • 使用自定义的 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 ,且互相之间的冲突概率几乎为零。

    3.获取文档

    为了从 Elasticsearch 中检索出文档,我们仍然使用相同的 _index , _type , 和 _id ,但是 HTTP 谓词更改为 GET :

    GET /website/blog/123?pretty
    

    响应体包括目前已经熟悉了的元数据元素,再加上 _source 字段,这个字段包含我们索引数据时发送给 Elasticsearch 的原始 JSON 文档:

    {
      "_index" :   "website",
      "_type" :    "blog",
      "_id" :      "123",
      "_version" : 1,
      "found" :    true,
      "_source" :  {
          "title": "My first blog entry",
          "text":  "Just trying this out...",
          "date":  "2014/01/01"
      }
    }
    

    在请求的查询串参数中加上 pretty 参数,正如前面的例子中看到的,这将会调用 Elasticsearch 的 pretty-print 功能,该功能 使得 JSON 响应体更加可读。但是, _source 字段不能被格式化打印出来。相反,我们得到的 _source 字段中的 JSON 串,刚好是和我们传给它的一样。

    GET 请求的响应体包括 {“found”: true} ,这证实了文档已经被找到。 如果我们请求一个不存在的文档,我们仍旧会得到一个 JSON 响应体,但是 found 将会是 false 。 此外, HTTP 响应码将会是 404 Not Found ,而不是 200 OK 。

    我们可以通过传递 -i 参数给 curl 命令,该参数能够显示响应的头部:

    curl -i -XGET http://localhost:9200/website/blog/124?pretty
    

    显示响应头部的响应体现在类似这样:

    HTTP/1.1 404 Not Found
    Content-Type: application/json; charset=UTF-8
    Content-Length: 83
    
    {
      "_index" : "website",
      "_type" :  "blog",
      "_id" :    "124",
      "found" :  false
    }
    

    获取文档的指定资源
    默认情况下, GET 请求会返回整个文档,这个文档正如存储在 _source 字段中的一样。但是也许你只对其中的 title 字段感兴趣。单个字段能用 _source 参数请求得到,多个字段也能使用逗号分隔的列表来指定。

    GET /website/blog/123?_source=title,text
    

    该 _source 字段现在包含的只是我们请求的那些字段,并且已经将 date 字段过滤掉了。

    {
      "_index" :   "website",
      "_type" :    "blog",
      "_id" :      "123",
      "_version" : 1,
      "found" :   true,
      "_source" : {
          "title": "My first blog entry" ,
          "text":  "Just trying this out..."
      }
    }
    

    或者,如果你只想得到 _source 字段,不需要任何元数据,你能使用 _source 字段提取:

    GET /website/blog/123/_source
    

    那么返回的的内容如下所示:

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

    4.更新文档

    在 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 按前述完全相同方式执行以下过程:

    • 从旧文档构建 JSON
    • 更改该 JSON
    • 删除旧文档
    • 索引一个新文档
      唯一的区别在于, update API 仅仅通过一个客户端请求来实现这些步骤,而不需要单独的 get 和 index 请求。
    展开全文
  • ElasticSearch Rest API交互

    2021-05-02 00:29:46
    第一个业务需求是存储员工数据。这将会以员工文档的形式存储:一个文档代表一个员工。存储数据Elasticsearch 的行为叫做索引,但在索引一个文档之前,需要确定将文档存储在哪...

    第一个业务需求是存储员工数据。这将会以 员工文档 的形式存储:一个文档代表一个员工。存储数据到 Elasticsearch 的行为叫做 索引 ,但在索引一个文档之前,需要确定将文档存储在哪里。

    一个 Elasticsearch 集群可以 包含多个 索引 ,相应的每个索引可以包含多个 类型 。这些不同的类型存储着多个 文档 ,每个文档又有 多个 属性 。

    Index Versus Index Versus Index

    你也许已经注意到 索引 这个词在 Elasticsearch 语境中有多种含义, 这里有必要做一些说明:

    索引(名词):

    如前所述,一个 索引 类似于传统关系数据库中的一个 数据库 ,是一个存储关系型文档的地方。 索引 (index) 的复数词为 indices 或 indexes 。

    索引(动词):

    索引一个文档 就是存储一个文档到一个 索引 (名词)中以便被检索和查询。这非常类似于 SQL 语句中的 INSERT 关键词,除了文档已存在时,新文档会替换旧文档情况之外。

    倒排索引:

    关系型数据库通过增加一个 索引 比如一个 B树(B-tree)索引 到指定的列上,以便提升数据检索速度。Elasticsearch 和 Lucene 使用了一个叫做 倒排索引 的结构来达到相同的目的。

    + 默认的,一个文档中的每一个属性都是 被索引 的(有一个倒排索引)和可搜索的。一个没有倒排索引的属性是不能被搜索到的。我们将在 倒排索引 讨论倒排索引的更多细节。

    对于员工目录,我们将做如下操作:

    • 每个员工索引一个文档,文档包含该员工的所有信息。

    • 每个文档都将是 employee 类型 。

    • 该类型位于 索引 megacorp 内。

    • 该索引保存在我们的 Elasticsearch 集群中。

    实践中这非常简单(尽管看起来有很多步骤),我们可以通过一条命令完成所有这些动作:

    PUT http://10.42.92.184/es/megacorp/employee/1
    
    {
        "first_name" : "John",
        "last_name" :  "Smith",
        "age" :        25,
        "about" :      "I love to go rock climbing",
        "interests": [ "sports", "music" ]}
    

    拷贝为 curl在 Sense 中查看 

    注意,路径 /megacorp/employee/1 包含了三部分的信息:

    • megacorp

    • 索引名称

    • employee

    • 类型名称

    • 1

    • 特定雇员的ID

    请求体 —— JSON 文档 —— 包含了这位员工的所有详细信息,他的名字叫 John Smith ,今年 25 岁,喜欢攀岩。

    很简单!无需进行执行管理任务,如创建一个索引或指定每个属性的数据类型之类的,可以直接只索引一个文档。Elasticsearch 默认地完成其他一切,因此所有必需的管理任务都在后台使用默认设置完成。

    进行下一步前,让我们增加更多的员工信息到目录中:

    PUT http://10.42.92.184/es/megacorp/employee/2
    
    {
        "first_name" :  "Jane",
        "last_name" :   "Smith",
        "age" :         32,
        "about" :       "I like to collect rock albums",
        "interests":  [ "music" ]}
    

    PUT /http://10.42.92.184/es/megacorp/employee/3
    
    {
        "first_name" :  "Douglas",
        "last_name" :   "Fir",
        "age" :         35,
        "about":        "I like to build cabinets",
        "interests":  [ "forestry" ]}
    

    查询员工数据,可以看到之前插入的3条数据

    get http://10.42.92.184/es/megacorp/employee/_search
    
    {
        "took": 25,
        "timed_out": false,
        "_shards": {
            "total": 5,
            "successful": 5,
            "failed": 0
        },
        "hits": {
            "total": 3,
            "max_score": 1.0,
            "hits": [
                {
                    "_index": "megacorp",
                    "_type": "employee",
                    "_id": "2",
                    "_score": 1.0,
                    "_source": {
                        "first_name": "Jane",
                        "last_name": "Smith",
                        "age": 32,
                        "about": "I like to collect rock albums",
                        "interests": [
                            "music"
                        ]
                    }
                },
                {
                    "_index": "megacorp",
                    "_type": "employee",
                    "_id": "1",
                    "_score": 1.0,
                    "_source": {
                        "first_name": "John",
                        "last_name": "Smith",
                        "age": 25,
                        "about": "I love to go rock climbing",
                        "interests": [
                            "sports",
                            "music"
                        ]
                    }
                },
                {
                    "_index": "megacorp",
                    "_type": "employee",
                    "_id": "3",
                    "_score": 1.0,
                    "_source": {
                        "first_name": "Douglas",
                        "last_name": "Fir",
                        "age": 35,
                        "about": "I like to build cabinets",
                        "interests": [
                            "forestry"
                        ]
                    }
                }
            ]
        }
    }
    

    好了,今天就先到这里,下一节课准备 教大家如何进行更新和删除数据,感兴趣的留言

    展开全文
  • elasticsearch(二)

    2018-08-14 14:25:17
    最近的索引请求将获胜:无论最后一个文档被索引,都将被唯一存储在 Elasticsearch 中。如果其他人同时更改这个文档,他们的更改将丢失。 很多时候这是没有问题的。也许我们的主数据存储是一个关系型数据库,我们...

    处理冲突

    当我们使用 index API 更新文档 ,可以一次性读取原始文档,做我们的修改,然后重新索引 整个文档 。 最近的索引请求将获胜:无论最后哪一个文档被索引,都将被唯一存储在 Elasticsearch 中。如果其他人同时更改这个文档,他们的更改将丢失。

    很多时候这是没有问题的。也许我们的主数据存储是一个关系型数据库,我们只是将数据复制到 Elasticsearch 中并使其可被搜索。 也许两个人同时更改相同的文档的几率很小。或者对于我们的业务来说偶尔丢失更改并不是很严重的问题。

    但有时丢失了一个变更就是 非常严重的 。试想我们使用 Elasticsearch 存储我们网上商城商品库存的数量, 每次我们卖一个商品的时候,我们在 Elasticsearch 中将库存数量减少。

    有一天,管理层决定做一次促销。突然地,我们一秒要卖好几个商品。 假设有两个 web 程序并行运行,每一个都同时处理所有商品的销售,如图 图 7 所示。

    图 7. Consequence of no concurrency control

    Consequence of no concurrency control

     

    web_1 对 stock_count 所做的更改已经丢失,因为 web_2 不知道它的 stock_count 的拷贝已经过期。 结果我们会认为有超过商品的实际数量的库存,因为卖给顾客的库存商品并不存在,我们将让他们非常失望。

    变更越频繁,读数据和更新数据的间隙越长,也就越可能丢失变更。

    在数据库领域中,有两种方法通常被用来确保并发更新时变更不会丢失:

    悲观并发控制

    这种方法被关系型数据库广泛使用,它假定有变更冲突可能发生,因此阻塞访问资源以防止冲突。 一个典型的例子是读取一行数据之前先将其锁住,确保只有放置锁的线程能够对这行数据进行修改。

    乐观并发控制

    Elasticsearch 中使用的这种方法假定冲突是不可能发生的,并且不会阻塞正在尝试的操作。 然而,如果源数据在读写当中被修改,更新将会失败。应用程序接下来将决定该如何解决冲突。 例如,可以重试更新、使用新的数据、或者将相关情况报告给用户。

     

    乐观并发控制

    Elasticsearch 是分布式的。当文档创建、更新或删除时, 新版本的文档必须复制到集群中的其他节点。Elasticsearch 也是异步和并发的,这意味着这些复制请求被并行发送,并且到达目的地时也许 顺序是乱的。 Elasticsearch 需要一种方法确保文档的旧版本不会覆盖新的版本。

    当我们之前讨论 index , GET 和 delete 请求时,我们指出每个文档都有一个 _version (版本)号,当文档被修改时版本号递增。 Elasticsearch 使用这个 _version 号来确保变更以正确顺序得到执行。如果旧版本的文档在新版本之后到达,它可以被简单的忽略。

    我们可以利用 _version 号来确保 应用中相互冲突的变更不会导致数据丢失。我们通过指定想要修改文档的 version 号来达到这个目的。 如果该版本不是当前版本号,我们的请求将会失败。

    让我们创建一个新的博客文章:

    PUT /website/blog/1/_create
    {
      "title": "My first blog entry",
      "text":  "Just trying this out..."
    }

    拷贝为 CURL

    响应体告诉我们,这个新创建的文档 _version 版本号是 1 。现在假设我们想编辑这个文档:我们加载其数据到 web 表单中, 做一些修改,然后保存新的版本。

    首先我们检索文档:

    GET /website/blog/1

    拷贝为 CURL

    响应体包含相同的 _version 版本号 1 :

    {
      "_index" :   "website",
      "_type" :    "blog",
      "_id" :      "1",
      "_version" : 1,
      "found" :    true,
      "_source" :  {
          "title": "My first blog entry",
          "text":  "Just trying this out..."
      }
    }

    现在,当我们尝试通过重建文档的索引来保存修改,我们指定 version 为我们的修改会被应用的版本:

    PUT /website/blog/1?version=1 
    {
      "title": "My first blog entry",
      "text":  "Starting to get the hang of this..."
    }

    拷贝为 CURL

    我们想这个在我们索引中的文档只有现在的 _version 为 1 时,本次更新才能成功。

    此请求成功,并且响应体告诉我们 _version 已经递增到 2 :

    {
      "_index":   "website",
      "_type":    "blog",
      "_id":      "1",
      "_version": 2
      "created":  false
    }

    拷贝为 CURL

    然而,如果我们重新运行相同的索引请求,仍然指定 version=1 , Elasticsearch 返回 409 ConflictHTTP 响应码,和一个如下所示的响应体:

    {
       "error": {
          "root_cause": [
             {
                "type": "version_conflict_engine_exception",
                "reason": "[blog][1]: version conflict, current [2], provided [1]",
                "index": "website",
                "shard": "3"
             }
          ],
          "type": "version_conflict_engine_exception",
          "reason": "[blog][1]: version conflict, current [2], provided [1]",
          "index": "website",
          "shard": "3"
       },
       "status": 409
    }

    拷贝为 CURL

    这告诉我们在 Elasticsearch 中这个文档的当前 _version 号是 2 ,但我们指定的更新版本号为 1 。

    我们现在怎么做取决于我们的应用需求。我们可以告诉用户说其他人已经修改了文档,并且在再次保存之前检查这些修改内容。 或者,在之前的商品 stock_count 场景,我们可以获取到最新的文档并尝试重新应用这些修改。

    所有文档的更新或删除 API,都可以接受 version 参数,这允许你在代码中使用乐观的并发控制,这是一种明智的做法。

    通过外部系统使用版本控制编辑

    一个常见的设置是使用其它数据库作为主要的数据存储,使用 Elasticsearch 做数据检索, 这意味着主数据库的所有更改发生时都需要被复制到 Elasticsearch ,如果多个进程负责这一数据同步,你可能遇到类似于之前描述的并发问题。

    如果你的主数据库已经有了版本号 — 或一个能作为版本号的字段值比如 timestamp — 那么你就可以在 Elasticsearch 中通过增加 version_type=external 到查询字符串的方式重用这些相同的版本号, 版本号必须是大于零的整数, 且小于 9.2E+18 — 一个 Java 中 long 类型的正值。

    外部版本号的处理方式和我们之前讨论的内部版本号的处理方式有些不同, Elasticsearch 不是检查当前 _version 和请求中指定的版本号是否相同, 而是检查当前 _version 是否 小于 指定的版本号。 如果请求成功,外部的版本号作为文档的新 _version 进行存储。

    外部版本号不仅在索引和删除请求是可以指定,而且在 创建 新文档时也可以指定。

    例如,要创建一个新的具有外部版本号 5 的博客文章,我们可以按以下方法进行:

    PUT /website/blog/2?version=5&version_type=external
    {
      "title": "My first external blog entry",
      "text":  "Starting to get the hang of this..."
    }

    拷贝为 CURL

    在响应中,我们能看到当前的 _version 版本号是 5 :

    {
      "_index":   "website",
      "_type":    "blog",
      "_id":      "2",
      "_version": 5,
      "created":  true
    }

    现在我们更新这个文档,指定一个新的 version 号是 10 :

    PUT /website/blog/2?version=10&version_type=external
    {
      "title": "My first external blog entry",
      "text":  "This is a piece of cake..."
    }

    拷贝为 CURL

    请求成功并将当前 _version 设为 10 :

    {
      "_index":   "website",
      "_type":    "blog",
      "_id":      "2",
      "_version": 10,
      "created":  false
    }

    如果你要重新运行此请求时,它将会失败,并返回像我们之前看到的同样的冲突错误, 因为指定的外部版本号不大于 Elasticsearch 的当前版本号。

    展开全文
  • 最近的索引请求将获胜:无论最后一个文档被索引,都将被唯一存储在 Elasticsearch 中。如果其他人同时更改这个文档,他们的更改将丢失。 很多时候这是没有问题的。也许我们的主数据存储是一个关系型数据库,我们...
  • ElasticSearch-冲突处理

    千次阅读 2017-10-18 10:32:30
    当我们使用indexAPI更新文档时,可以一次性读取原始文档,然后重新索引整个文档,最近的索引请求将获胜:无论最后一个文档被索引,都将被唯一存储在ElasticSearch中。如果其他人同时更改这个文档,他们的更改将...
  • 最近的索引请求将获胜:无论最后一个文档被索引,都将被唯一存储在 Elasticsearch 中。如果其他人同时更改这个文档,他们的更改将丢失。 很多时候这是没有问题的。也许我们的主数据存储是一个关系型数据库,我们...
  • 摘要: 文章主要来源于官方文档的叙述,同时结合我自己的理解整合而...问题:当我们要在ES中存储数据的时候,数据应该存储在主分片和复制分片中的一个中去;当我们在ES中检索数据的时候,又是怎么判断要查询的数据是属
  • Elasticsearch 入门(四)

    2019-10-04 19:09:43
    问题:当我们要在ES中存储数据的时候,数据应该存储在主分片和复制分片中的一个中去;当我们在ES中检索数据的时候,又是怎么判断要查询的数据是属于一个分片。 数据存储到分片的过程是一定规则的,并不是...
  • 问题:当我们要在ES中存储数据的时候,数据应该存储在主分片和复制分片中的一个中去;当我们在ES中检索数据的时候,又是怎么判断要查询的数据是属于一个分片。   数据存储到分片的过程是一定规则的,并不...
  • 因为我一开始把数据存储在mongodb中,所以我是用mongo-connector将数据同步到elasticsearch后再指定的分词器 ``` "settings": { "index": { "number_of_shards": "1", "provided_name": "ebook", "creation_...
  • 当我们要在ES中存储数据的时候,数据应该存储在主分片和复制分片中的一个中去;当我们在ES中检索数据的时候,又是怎么判断要查询的数据是属于一个分片。 进程不能是随机的,因为我们将来要检索文档。事实上,...
  • 一、Hadoop生态系统 Hadoop利用大量廉价的计算机,提供了一个可扩展强,可靠性高的机制;并利用廉价的方式来存储大量数据。Hadoop把任务分成任务片,分布在数千台计算机上,从而进行快速分析,并分布式存储...数据在哪
  • 现在做营销功能,有些数据(优惠券),不知道是用redis还是搜索引擎来存储相关数据 ...不知道这种数据种方式存储比较合适,缓存应该速度更快,但搜索引擎对过滤和分页的支持更好,不知谁能帮我分析
  • node1接收到请求后,会根据请求中携带的参数"文档id"判断出该文档应该存储在具体一个shard中. shard = hash(rounting) % number_of_primary_shards 比如, 计算出的结果是该条数据存在在shard0分片上. node1通过元...
  • 其次:node1接到请求之后,会根据请求中携带的参数“文档id”判断出该文档应该存储在具体一个shard中 shard = hash(routing) % numberofprimary_shards ,比如shard0;其次就是node1通过元数据信息可以知道shard...
  • 处理冲突

    2018-02-09 14:51:16
    最近的索引请求将获胜:无论最后一个文档被索引,都将被唯一存储在 Elasticsearch 中。如果其他人同时更改这个文档,他们的更改将丢失。很多时候这是没有问题的。也许我们的主数据存储是一个关系型数据库,我们...
  • Elastcisearch记录

    2018-02-13 13:50:29
    实时 JSON文档在 Elasticsearch 中, 每个字段的所有数据 都是 默认被索引的 。 即每个字段都有为了快速检索设置的专用倒排索引文档 ==根对象 ID唯一文档本身数据 1.index索引--文档在哪存放 2.type文档表示的对象...
  • 去哪儿网基于Mesos Docker的Elasticsearch容器化私有云 滴滴统一资源调度平台建设实践 亚马逊云平台计算服务进化之路 京东云为企业提供智能化之路 中移苏研存储产品化之路 百度基于Druid的大数据采集即计算实践 ...
  • 主要是对Elasticsearch的应用,将所有商品数据封装好后添加到Elasticsearch的索引库中,然后进行搜索过滤,查询相应的商品信息。 2.11 秒杀微服务 主要接口有: 添加参加秒杀的商品 查询秒杀商品 创建秒杀地址 ...
  • 1、Lucene, elasticSearch 2、Redis: Redis sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的 是所有的成员ÿ...

空空如也

空空如也

1 2
收藏数 26
精华内容 10
关键字:

elasticsearch数据存储在哪