Elasticsearch介绍,基本查询详解

栏目: 后端 · 发布时间: 5年前

内容简介:​ elasticsearch是一个近实时分布式搜索和分析引擎,它用于全文搜索、结构化搜索、分析以及将这三者混合使用,使用java编写,基于Lucene 实现建议安装Elasticsearch+Kibana,在Kibana的操作界面对es进行操作Elasticsearch提供了RESTful接口可以对Elasticsearch进行操作

​ elasticsearch是一个近实时分布式搜索和分析引擎,它用于全文搜索、结构化搜索、分析以及将这三者混合使用,使用 java 编写,基于Lucene 实现

优势:

  1. 分布式的实时文件存储,每个字段都被索引并可被搜索

  2. 实时分析的分布式搜索引擎

  3. 横向可扩展:支持上百台服务节点的扩展,集群增加机器简单,支持处理PB级数据

  4. 分片机制:

    允许水平分割扩展数据,允许分片和并行操作从而提高性能和吞吐量

    提供高性能:同一个索引可以分多个主分片( primary shard ),每个主分片拥有自己的副本分片( replica shard ),每个副本分片都可以提供服务,提升系统搜索请求的吞吐量和性能

    提供高可用性:同一个索引可以分多个主分片,每个主分片拥有零个或者多个副本,如果主分片挂了,可以从副本分片中选择一个作为主分片继续提供服务

  5. 隐藏复杂实现:Elasticsearch 内部隐藏了分布式系统的复杂性,我们不用去关心它是如何做到高可用,可扩展,高性能的

  6. 易用开源:不需要额外配置,就可以运行一个Elasticsearch服务,开源

基本概念

  1. Cluster :集群

    一个集群包含多个节点,对外提供服务,每个节点属于哪个集群通过配置文件中的集群名称决定

  2. Node :节点

    集群中的一个节点,每个节点也有一个名称,默认是随机分配,也可以自己指定,在es集群中通过节点名称进行管理和通信

  3. Index :索引

    索引是具有相同结构的文档集合,作用相当于 mysql 中的库

  4. Type :类型

    一个索引可以对应一个或者多个类型,类型可以当做是索引的逻辑分区,作用相当于mysql中的表

  5. Document :文档

    存储在es中的一个 JSON 格式的字符串,每一个文档有一个文档ID,如果没有自己指定ID,系统会自动生成一个ID,文档的index/type/id必须是唯一的,作用相当于mysql中的行

  6. field :字段

    一个文档会包含多个字段,每个字段都对应一个字段类型,类似于mysql中的列

  7. shard :分片

    es中分为 primary shard 主分片和 replica shard 副本分片

    主分片:当存一个文档的时候会先存储在主分片中,然后复制到不同的副本分片中,默认一个索引会有5个主分片,当然可以自己指定分片数量,当分片一旦建立,分片数量不能改变

    副本分片:每一个主分片会有零个或者多个副本,副本主要是主分片的复制,通过副本分片可以提供高可用性,当一个主分片挂了,可以从副本分片中选择一个作为主分片,还可以提高性能,所以主分片不能和副本分片部署在相同的节点上

  8. replica :复制

    复制是为了防止单点问题,可以做到对故障进行转移,保证系统的高可用

  9. 映射

    描述数据在每个字段内如何存储,是定义存储和索引的文档类型及字段的过程,索引中的每一个文档都有一个类型,每种类型都有它自己的映射,一个映射定义了文档结构内每个字段的数据类型

    使用 GET /index/_mapping/type 获取对应的 /index/type 的映射信息

基本操作

建议安装Elasticsearch+Kibana,在Kibana的操作界面对es进行操作

Elasticsearch提供了RESTful接口可以对Elasticsearch进行操作

Kibana操作页面

在Kibana的Dev Tools界面可以对es进行操作,在console界面敲命令,点执行,会在右面输出结果

Elasticsearch介绍,基本查询详解

验证Elasticsearch是否安装成功

http://localhost:9200/?pretty

{
  "name" : "UzOujcc", //节点名称
  "cluster_name" : "mx", //集群名称,我自己设置的
  "cluster_uuid" : "d2K1M95DRzG9XOPDOR_DEQ",
  "version" : {
    "number" : "6.2.4", //集群版本
    "build_hash" : "ccec39f",
    "build_date" : "2018-04-12T20:37:28.497551Z",
    "build_snapshot" : false,
    "lucene_version" : "7.2.1",
    "minimum_wire_compatibility_version" : "5.6.0",
    "minimum_index_compatibility_version" : "5.0.0"
  },
  "tagline" : "You Know, for Search"
}

es提供了一套api,叫做cat api,可以查看es中的信息数据

查看集群健康状况

命令: GET /_cat/health?v

Elasticsearch介绍,基本查询详解

status 代表着集群的健康程度

green
yellow
red

索引操作

查看索引信息

命令: GET _cat/indices?v

Elasticsearch介绍,基本查询详解

有五个索引,都是的测试数据

新建索引

命令: PUT /myindex

{
  "acknowledged": true,
  "shards_acknowledged": true,
  "index": "myindex"
}

删除索引

命令: DELETE myindex

{
  "acknowledged": true
}

文档操作

添加文档

添加文档是向索引中添加一条文档,让其能够搜索,文档格式是json串,如果es中有相同id的文档存在则更新这个文档

当创建文档的时候,如果索引不存在,则会自动创建该索引,而且es默认会对document每个field都建立倒排索引,让其可以被搜索

命令:

PUT /index/type/id 
{ 
    "json数据结构体 "
}

例:

PUT /school/student/1
{
  "name":"张三",
  "age":21,
  "class":2,
  "gender":"男"
}

返回:

{
  "_index": "school", //索引
  "_type": "student", //类型
  "_id": "1", //id,如果不指定则会系统生成一个20位的id,文档被分到那个分片上就是根据id的散劣值进行控制
  "_version": 1, //文档版本号,通过这个进行并发控制
  "result": "created", //操作类型
  "_shards": { //分片信息
    "total": 2, //文档被创建时在多少个分片进行了操作(包括主分片和副本分片)
    "successful": 1, //添加成功的索引分片数量
    "failed": 0 //失败的索引分片数量
  },
  "_seq_no": 0,
  "_primary_term": 1
}

修改文档

方式1:使用put方式更新文档

PUT /school/student/1
{
  "name":"吕布",
  "age":21,
  "class":2,
  "gender":"男"
}

返回:

{
  "_index": "school",
  "_type": "student",
  "_id": "1",
  "_version": 2, //版本号+1
  "result": "updated", // 修改
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 1,
  "_primary_term": 1
}

这种方式替换需要带上所有的field,才能进行信息的修改,操作类似于覆盖

方式2:post更新文档

POST /school/student/1/_update
{
  "doc": {
    "name":"吕布1"
  }
}

使用post更新文档,可以只更新部分字段

查询文档

查询单条文档

命令: GET /school/student/1

返回:

{
  "_index": "school",
  "_type": "student",
  "_id": "1",
  "_version": 3,
  "found": true,
  "_source": {
    "name": "吕布1",
    "age": 21,
    "class": 2,
    "gender": "男"
  }
}

删除文档

命令: DELETE school/student/1

返回:

{
  "_index": "school",
  "_type": "student",
  "_id": "1",
  "_version": 4,
  "result": "deleted", //删除
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 3,
  "_primary_term": 1
}

这时在查询就会显示 "found": false

映射与分析

Elasticsearch 中的数据可以概括的分为两类:精确值和全文

  1. 精确值:精确值是确定的值,比如用户ID,字符串也可以表示精确值,例如用户名或邮箱地址。对于精确值来讲, Foofoo 是不同的,精确值的查询简单,要么匹配查询,要么不匹配
  2. 全文:全文是指文本数据(通常以人类容易识别的语言书写),例如一个推文的内容或一封邮件的内容,全文的查询较为复杂,他需要的是匹配查询的程度有多大

在es中使用 倒排索引来进行快速的全文搜索。一个倒排索引由文档中所有不重复词的列表构成,对于其中每个词,有一个包含它的文档列表, 倒排索引 具体内容请戳: https://www.elastic.co/guide/cn/elasticsearch/guide/current/inverted-index.html

映射

es中的映射( mapping )用来描述数据在每个字段内如何存储,是定义存储和索引的文档类型及字段的过程,索引中的每一个文档都有一个类型,每种类型都有它自己的映射,一个映射定义了文档结构内每个字段的数据类型,作用相当于 mysql 中的 DDL 语句

查询索引类型的映射

GET /ad/_mapping/phone

{
  "school": {
    "mappings": {
      "student": {
        "properties": {
          "age": {
            "type": "long"
          },
          "class": {
            "type": "long"
          },
          "gender": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "name": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      }
    }
  }
}

动态映射

动态映射不需要事先定义映射,文档在写入es的时候,会根据文档字段自动识别类型

映射规则:

Json 数据类型 es 数据类型
null 没有字段添加
true,false boolean
Integer long
object object
array 依赖于数组中首个非空值
string text和keyword
日期 date或text

静态映射

静态映射需要事先定义好映射,包含文档的各个字段及其类型

PUT books
{
  "mappings": {
    "book":{
      "properties": {
        "id":{"type": "long"},
        "bookName":{"type": "text"},
        "ad":{"type": "text"}
      }
    }
  }
}

es中的字符串类型分为 keywordtext

keyword
text

有时候一个字段同时拥有全文类型(text)和关键字类型(keyword)是有用的:一个用于全文搜索,另一个用于聚合和排序。这可以通过多字段类型来实现(动态映射是字符串的默认映射类型)

多种查询

url参数搜索

这种方式就是类似于get请求,将请求参数拼接到链接上,例 GET /school/student/_search?参数 ,多个参数用&分开

查询所有

命令: GET /school/student/_search

返回:

{
  "took": 7, //查询耗时,毫秒
  "timed_out": false, //是否超时,timeout 不是停止执行查询,它仅仅是告知正在协调的节点返回到目前为止收集的结果并且关闭连接
  "_shards": {
    "total": 5, //请求的分片数量,索引拆成了5个分片,所以对于搜索请求,会打到所有的primary shard
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 2, //符合条件的总条数,这里查的是所有
    "max_score": 1, //匹配分数
    "hits": [ //数据
      {
        "_index": "school",
        "_type": "student",
        "_id": "2",
        "_score": 1,
        "_source": {
          "name": "houyi",
          "age": 23,
          "class": 2,
          "gender": "男"
        }
      },
      {
        "_index": "school",
        "_type": "student",
        "_id": "1",
        "_score": 1,
        "_source": {
          "name": "吕布",
          "age": 21,
          "class": 2,
          "gender": "男"
        }
      }
    ]
  }
}

多索引,多type搜索

在URL中指定特殊的索引和类型进行多索引,多type搜索

  1. /_search :在所有的索引中搜索所有的类型
  2. /school/_search :在 school 索引中搜索所有的类型
  3. /school,ad/_search :在 schoolad 索引中搜索所有的类型
  4. /s*,a*/_search :在所有以 ga 开头的索引中所有所有的类型
  5. /school/student/_search :在 school 索引中搜索 student 类型
  6. /school,ad/student,phone/_search :在 schoolad 索引上搜索 studentphone 类型
  7. /_all/student,phone/_search :在所有的索引中搜索 studentphone 类型

按条件查询

命令: GET /school/student/_search?q=name:houyi

查询name是houyi的记录

更多搜索参数:

Elasticsearch介绍,基本查询详解

查询DSL

elasticsearch提供了基于JSON的完整查询DSL来定义查询,DSL拥有一套查询组件,这些组件可以以无限组合的方式进行搭配,构建各种复杂的查询

  1. 叶子语句:就像match语句,被用于将查询的字符串与一个字段或多个字段进行对比(单个条件)

    比如:

    GET /ad/phone/_search
    {
      "query": {
        "match": {
          "name": "phone"
        }
      }
    }
  2. 复合查询:用户合并其他查询语句,比如一个 bool 语句,允许你在需要的时候组合其他语句,包括 mustmust_notshouldfilter 语句(多条件组合查询)

    比如:

    GET /ad/phone/_search
    {
      "query": {
        "bool": {
          "must": [
            {"match": {
              "name": "phone"
            }}
          ]
          , "must_not": [
            {"match": {
              "color": "red"
            }}
          ]
          , "should": [
            {"match": {
              "price": 5000
            }}
          ]
          , "filter": {
              "term": {
                "label": "phone"
              }
          }
        }
      }
    }

    must :表示文档一定要包含查询的内容

    must_not :表示文档一定不要包含查询的内容

    should :表示如果文档匹配上可以增加文档相关性得分

事实上我们可以使用两种结构化语句: 结构化查询 query DSL 和结构化过滤 Filter DSL

  1. 结构化查询 query DSL

    用于检查内容与条件是否匹配,内容查询中使用的bool和match字句,用于计算每个文档的匹配得分,元字段_score表示匹配度,查询的结构中以query参数开始来执行内容查询

  2. 结构化过滤 Filter DSL

    只是简单的决定文档是否匹配,内容过滤中使用的term和range字句,会过滤 调不匹配的文档,并且不影响计算文档匹配得分

    使用过滤查询会被es自动缓存用来提高效率

原则上来说,使用查询语句做全文本搜索或其他需要进行相关性评分的时候,剩下的全部用过滤语句

新建一个稍微复杂的索引,添加三条文档

PUT /ad/phone/1
{
  "name":"phone 8",
  "price": 6000,
  "color":"white",
  "ad":"this is a white phone",
  "label":["white","nice"]
}

PUT /ad/phone/2
{
  "name":"xiaomi 8",
  "price": 4000,
  "color":"red",
  "ad":"this is a red phone",
  "label":["white","xiaomi"]
}

PUT /ad/phone/3
{
  "name":"huawei p30",
  "price": 5000,
  "color":"white",
  "ad":"this is a white phone",
  "label":["white","huawei"]
}

查询示例:

  1. 获取所有

    GET /ad/phone/_search
    {
      "query": {
        "match_all": {}
      }
    }

    match_all 匹配所有数据,返回的结果中元字段 _score 得分为1

  2. 分页查询,从第二条开始,查两条(不要使用 fromsize 进行深度分页,会有性能问题)

    GET /ad/phone/_search
    {
      "query": {
        "match_all": {}
      },
      "from": 1,
      "size": 2
    }

    这种分页方式如果进行深度分页,比如到100页,每页十条数据,它会从每个分片都查询出100*10条数据,假设有五个分片,就是5000条数据,然后在内存中进行排序,然后返回拍过序之后的集合中的第1000-1010条数据

  3. 指定查询出来的数据返回的字段

    GET /ad/phone/_search
    {
      "query": {
        "match_all": {}
      },
      "_source": ["name","price"]
    }

    返回的数据中只返回 nameprice 字段

  4. ad字段中包含单词white

    GET /ad/phone/_search
    {
      "query": {
        "match": {
          "ad": "white"
        }
      }
    }

    返回的结果中元字段 _score 有评分,说明使用 query 会计算评分

  5. ad字段中包含单词white,并按照价格升序排列

    GET /ad/phone/_search
    {
      "query": {
        "match": {
          "ad": "white"
        }
      }, 
      "sort": [
        {
          "price": {
            "order": "asc"
          }
        }
      ]
    }
  6. 价格字段大于5000

    GET /ad/phone/_search
    {
      "query": {
        "bool": {
          "filter": {
            "range": {
              "price": {
                "gt": 5000
              }
            }
          }
        }
      }
    }

    返回的结果中元字段 _score 字段等于0,没评分,说明使用 filter 不会计算评分

  7. ad字段中包含单词white,价格字段大于5000

    GET /ad/phone/_search
    {
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "ad": "white"
              }
            }
          ], 
          "filter": {
            "range": {
              "price": {
                "gt": 5000
              }
            }
          }
        }
      }
    }
  8. 查询 name 字段包含单词 phone 的文档的数量

    GET /ad/phone/_count
    {
      "query": {
        "match": {
          "name": "phone"
        }
      }
    }

搜索示例

  1. match_all 查询

    查询简单的匹配所有文档

    GET /ad/phone/_search
    {
      "query": {
        "match_all": {}
      }
    }
  2. match 查询

    支持全文搜索和精确查询,取决于字段是否支持全文检索

    全文检索:

    GET /ad/phone/_search
    {
      "query": {
        "match": {
          "ad": "a red"
        }
      }
    }

    全文检索会将查询的字符串先进行分词, a red 会分成为 ared ,然后在倒排索引中进行匹配,所以这条语句会将三条文档都查出来

    精确查询:

    GET /ad/phone/_search
    {
      "query": {
        "match": {
          "price": "6000"
        }
      }
    }

    对于精确值的查询,可以使用 filter 语句来取代 query,因为 filter 将会被缓存

    operator 操作:

    match 查询还可以接受 operator 操作符作为输入参数,默认情况下该操作符是 or 。我们可以将它修改成 and 让所有指定词项都必须匹配

    GET /ad/phone/_search
    {
      "query": {
        "match": {
          "ad": {
            "query": "a red",
            "operator": "and"
          }
        }
      }
    }

    精确度匹配:

    match 查询支持 minimum_should_match 最小匹配参数, 可以指定必须匹配的词项数用来表示一个文档是否相关。我们可以将其设置为某个具体数字(指需要匹配倒排索引的词的数量),更常用的做法是将其设置为一个百分数,因为我们无法控制用户搜索时输入的单词数量

    GET /ad/phone/_search
    {
      "query": {
        "match": {
          "ad": {
            "query": "a red",
            "minimum_should_match": "2"
          }
        }
      }
    }

    只会返回匹配上 ared 两个词的文档返回,如果 minimum_should_match 是1,则只要匹配上其中一个词,文档就会返回

  3. multi_match 查询

    多字段查询,比如查询 colorad 字段包含单词 red 的文档

    GET /ad/phone/_search
    {
      "query": {
        "multi_match": {
          "query": "red",
          "fields": ["color","ad"]
        }
      }
    }
  4. range 查询

    范围查询,查询价格大于4000小于6000的文档

    GET /ad/phone/_search
    {
      "query": {
        "range": {
          "price": {
            "gt": 4000,
            "lt": 6000
          }
        }
      }
    }

    范围查询操作符: gt (大于), gte (大于等于), lt (小于), lte (小于等于);

  5. term 查询

    精确值查询

    查询 price 字段等于6000的文档

    GET /ad/phone/_search
    {
      "query": {
        "term": {
          "price": {
            "value": "6000"
          }
        }
      }
    }

    查询 name 字段等于 phone 8 的文档

    GET /ad/phone/_search
    {
      "query": {
        "term": {
          "name": {
            "value": "phone 8"
          }
        }
      }
    }

    返回值如下,没有查询到名称为 phone 8 的文档

    {
      "took": 5,
      "timed_out": false,
      "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
      },
      "hits": {
        "total": 0,
        "max_score": null,
        "hits": []
      }
    }

    为什么没有查到 phone 8 的这个文档那,这里需要介绍一下 term 的查询原理

    term 查询会去倒排索引中寻找确切的 term ,它并不会走分词器,只会去配倒排索引 ,而 name 字段的 type 类型是 text ,会进行分词,将 phone 8 分为 phone8 ,我们使用 term 查询 phone 8 时倒排索引中没有 phone 8 ,所以没有查询到匹配的文档

    term 查询与 match 查询的区别

    • term 查询时,不会分词,直接匹配倒排索引
    • match 查询时会进行分词,查询 phone 8 时,会先分词成 phone8 ,然后去匹配倒排索引,所以结果会将 phone 8xiaomi 8 两个文档都查出来

    还有一点需要注意,因为 term 查询不会走分词器,但是回去匹配倒排索引,所以查询的结构就跟分词器如何分词有关系,比如新增一个 /ad/phone 类型下的文档, name 字段赋值为 Oppo ,这时使用 term 查询 Oppo 不会查询出文档,这时因为es默认是用的 standard 分词器,它在分词后会将单词转成小写输出,所以使用 oppo 查不出文档,使用小写 oppo 可以查出来

    GET /ad/phone/_search
    {
      "query": {
        "term": {
          "name": {
            "value": "Oppo" //改成oppo可以查出新添加的文档
          }
        }
      }
    }

    这里说的并不是想让你了解 standard 分词器,而是要get到所有像 term 这类的查询结果跟选择的分词器有关系,了解选择的分词器分词方式有助于我们编写查询语句

  6. terms 查询

    terms 查询与 term 查询一样,但它允许你指定多直进行匹配,如果这个字段包含了指定值中的任何一个值,那么这个文档满足条件

    GET /ad/phone/_search
    {
      "query": {
        "terms": {
          "ad": ["red","blue"]
        }
      }
    }
  7. exists 查询和 missing 查询

    用于查找那些指定字段中有值 ( exists ) 或无值 ( missing ) 的文档

    指定 name 字段有值:

    GET /ad/phone/_search
    {
      "query": {
        "bool": {
          "filter": {
            "exists": {
              "field": "name"
            }
          }
        }
      }
    }

    指定 name 字段无值:

    GET /ad/phone/_search
    {
      "query": {
        "bool": {
          "filter": {
            "missing": {
              "field": "name"
            }
          }
        }
      }
    }
  8. match_phrase 查询

    短语查询,精确匹配,查询 a red 会匹配 ad 字段包含 a red 短语的,而不会进行分词查询,也不会查询出包含 a 其他词 red 这样的文档

    GET /ad/phone/_search
    {
      "query": {
        "match_phrase": {
          "ad": "a red"
        }
      }
    }
  9. scroll 查询

    类似于分页查询,不支持跳页查询,只能一页一页往下查询, scroll 查询不是针对实时用户请求,而是针对处理大量数据,例如为了将一个索引的内容重新索引到具有不同配置的新索引中

    POST /ad/phone/_search?scroll=1m
    {
      "query": {
        "match_all": {}
      },
      "size": 1,
      "from": 0
    }

    返回值包含一个 "_scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAAAQFlV6T3VqY2NaVDBLRG5uZXdiZ0hFYUEAAAAAAAAAERZVek91amNjWlQwS0RubmV3YmdIRWFBAAAAAAAAABIWVXpPdWpjY1pUMEtEbm5ld2JnSEVhQQAAAAAAAAATFlV6T3VqY2NaVDBLRG5uZXdiZ0hFYUEAAAAAAAAAFBZVek91amNjWlQwS0RubmV3YmdIRWFB"

    下次查询的时候使用 _scroll_id 就可以查询下一页的文档

    POST /_search/scroll 
    {
        "scroll" : "1m", 
        "scroll_id" : "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAAAYFlV6T3VqY2NaVDBLRG5uZXdiZ0hFYUEAAAAAAAAAGRZVek91amNjWlQwS0RubmV3YmdIRWFBAAAAAAAAABYWVXpPdWpjY1pUMEtEbm5ld2JnSEVhQQAAAAAAAAAXFlV6T3VqY2NaVDBLRG5uZXdiZ0hFYUEAAAAAAAAAFRZVek91amNjWlQwS0RubmV3YmdIRWFB" 
    }
  10. multi get 查询

    允许基于索引,类型(可选)和id(以及可能的路由)获取多个文档,如果某个文档获取失败则将错误信息包含在响应中

    GET /ad/phone/_mget
    {
      "ids": ["1","8"]
    }
  11. bulk 批量操作

    bulk 批量操作可以在单次API调用中实现多个文档的 createindexupdatedelete 。这可以大大提高索引速度

    bulk 请求体如下

    { action: { metadata }}\n 
    { request body        }\n
    { action: { metadata }}\n
    { request body        }\n
    ...

    行为( action )必须是以下几种:

    | 行为 | 解释 |

    | ——– | —————————————————— |

    | create | 当文档不存在时创建之。详见《创建文档》 |

    | index | 创建新文档或替换已有文档。见《索引文档》和《更新文档》 |

    | update | 局部更新文档。见《局部更新》 |

    | delete | 删除一个文档。见《删除文档》 |

    在索引、创建、更新或删除时必须指定文档的 _index_type_id 这些元数据( metadata )

    例:

    PUT _bulk
    { "create" : { "_index" : "ad", "_type" : "phone", "_id" : "6" }}
    { "doc" : {"name" : "bulk"}}
    { "index" : { "_index" : "ad", "_type" : "phone", "_id" : "6" }}
    { "doc" : {"name" : "bulk"}}
    { "delete":{  "_index" : "ad", "_type" : "phone", "_id" : "1"}}
    { "update":{  "_index" : "ad", "_type" : "phone", "_id" : "3"}}
    { "doc" : {"name" : "huawei p20"}}

    返回:

    {
      "took": 137,
      "errors": true, //如果任意一个文档出错,这里返回true,
      "items": [ //items数组,它罗列了每一个请求的结果,结果的顺序与我们请求的顺序相同
        {
          //create这个文档已经存在,所以异常
          "create": { 
            "_index": "ad",
            "_type": "phone",
            "_id": "6",
            "status": 409,
            "error": {
              "type": "version_conflict_engine_exception",
              "reason": "[phone][6]: version conflict, document already exists (current version [2])",
              "index_uuid": "9F5FHqgISYOra_P09HReVQ",
              "shard": "2",
              "index": "ad"
            }
          }
        },
        {
          //index这个文档已经存在,会覆盖
          "index": { 
            "_index": "ad",
            "_type": "phone",
            "_id": "6",
            "_version": 3,
            "result": "updated",
            "_shards": {
              "total": 2,
              "successful": 1,
              "failed": 0
            },
            "_seq_no": 6,
            "_primary_term": 5,
            "status": 200
          }
        },
        {
          //删除  
          "delete": { 
            "_index": "ad",
            "_type": "phone",
            "_id": "1",
            "_version": 1,
            "result": "not_found",
            "_shards": {
              "total": 2,
              "successful": 1,
              "failed": 0
            },
            "_seq_no": 4,
            "_primary_term": 5,
            "status": 404
          }
        },
        {
          //修改  
          "update": { 
            "_index": "ad",
            "_type": "phone",
            "_id": "3",
            "_version": 3,
            "result": "noop",
            "_shards": {
              "total": 2,
              "successful": 1,
              "failed": 0
            },
            "status": 200
          }
        }
      ]
    }

    bulk 请求不是原子操作,它们不能实现事务。每个请求操作时分开的,所以每个请求的成功与否不干扰其它操作


以上所述就是小编给大家介绍的《Elasticsearch介绍,基本查询详解》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

算法:C语言实现

算法:C语言实现

塞奇威克 / 机械工业出版社 / 2006-9 / 69.00元

本书是Sedgewick彻底修订和重写的C算法系列的第一本。全书分为四部分,共16章,第一部分“基础知识”(第1-2章)介绍基本算法分析原理。第二部分“数据结构”(第3-5章)讲解算法分析中必须掌握的数据结构知识,主要包括基本数据结构,抽象数据结构,递归和树。一起来看看 《算法:C语言实现》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换