索引

创建索引 索引命名必须小写,不能以下划线开头

格式: PUT /索引名称

1. 创建索引 PUT /es_test

params

{
  "mappings": {
    "properties": {
      "name": {
        "type": "keyword"
      }
    }
  }
}

2. 设置分片和副本 PUT /es_test

params

{
    "settings" : {
        "number_of_shards" : 3, //设置分片数
        "number_of_replicas" : 2 //设置副本数
    }
}

3. 设置默认分词器 PUT /es_test

params

{
  "settings": {
    "index": {
      "analysis.analyzer.default.type": "ik_max_word" //设置 IK 分词器
    }
  }
}

4. 修改索引配置 PUT /es_test/_settings

{
    "index" : {
        "number_of_replicas" : 1
    }
}

查询索引

格式: GET /索引名称

1. 查询索引

GET /es_test

2. 查询索引是否存在

HEAD /es_test

删除索引

格式: DELETE /索引名称

DELETE /es_test

文档

添加(索引)文档

格式: [PUT | POST] /索引名称/[_doc | _create ]/id

1. 创建文档,指定id,如果id不存在,创建新的文档,否则先删除现有文档,再创建新的文档,版本会增加

PUT /es_test/_doc/1
{
"name": "张三",
"sex": 1,
"age": 25,
"address": "广州天河公园",
"remark": "java developer"
}

2. 创建文档,ES生成id

POST /es_test/_doc
{
"name": "张三",
"sex": 1,
"age": 25,
"address": "广州天河公园",
"remark": "java developer"
}

response

{
  "_index" : "es_test",
  "_type" : "_doc",
  "_id" : "pLvYHoIBp7dqYq6zm9s3",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 8,
  "_primary_term" : 1
}

3. Create

PUT /es_test/_create/1
{
"name": "张三",
"sex": 1,
"age": 25,
"address": "广州天河公园",
"remark": "java developer"
}

如果ID已经存在,会失败

response

{
  "error" : {
    "root_cause" : [
      {
        "type" : "version_conflict_engine_exception",
        "reason" : "[1]: version conflict, document already exists (current version [2])",
        "index_uuid" : "7WEF5qaKTAaNGBLCkwx8xQ",
        "shard" : "0",
        "index" : "es_test"
      }
    ],
    "type" : "version_conflict_engine_exception",
    "reason" : "[1]: version conflict, document already exists (current version [2])",
    "index_uuid" : "7WEF5qaKTAaNGBLCkwx8xQ",
    "shard" : "0",
    "index" : "es_test"
  },
  "status" : 409
}

更新索引 如果文档存在,现有文档会被删除,新的文档会被索引

1. 全量更新,替换整个json 全量更新,整个json都会替换,格式: [PUT | POST] /索引名称/_doc/id

PUT /es_test/_doc/1/
{
"name": "张三",
"sex": 1,
"age": 25
}

2. 使用_update部分更新 格式: POST /索引名称/_update/id

update不会删除原来的文档,而是实现真正的数据更新

部分更新:在原有文档上更新
Update -文档必须已经存在,更新只会对相应字段做增量修改

POST /es_test/_update/1
{
  "doc": {
    "age": 28
  }
}

文档不存在
response

{
  "error" : {
    "root_cause" : [
      {
        "type" : "document_missing_exception",
        "reason" : "[_doc][1111]: document missing",
        "index_uuid" : "7WEF5qaKTAaNGBLCkwx8xQ",
        "shard" : "0",
        "index" : "es_test"
      }
    ],
    "type" : "document_missing_exception",
    "reason" : "[_doc][1111]: document missing",
    "index_uuid" : "7WEF5qaKTAaNGBLCkwx8xQ",
    "shard" : "0",
    "index" : "es_test"
  },
  "status" : 404
}

3. 使用 _update_by_query 更新文档

POST /es_test/_update_by_query
{
  "query": { 
    "match": {
      "_id": 1
    }
  },
  "script": {
    "source": "ctx._source.age = 35"
  }
}

注意:POST和PUT都能起到创建/更新的作用,PUT需要对一个具体的资源进行操作也就是要确定id才能进行更新/创建,而POST是可以针对整个资源集合进行操作的,如果不写id就由ES生成一个唯一id进行创建新文档,如果填了id那就针对这个id的文档进行创建/更新

4. 并发场景下修改文档

_seq_no和_primary_term是对_version的优化,7.X版本的ES默认使用这种方式控制版本,所以当在高并发环境下使用乐观锁机制修改文档时,要带上当前文档的_seq_no和_primary_term进行更新:

  1. get /es_test/_doc/1
{
  "_index" : "es_test",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 4,
  "_seq_no" : 11,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "address" : "广州天河公园",
    "sex" : 1,
    "name" : "张三",
    "remark" : "java developer",
    "age" : 35
  }
}
  1. 带版本号修改
POST /es_test/_update/1?if_seq_no=11&if_primary_term=1
{
  "doc": {
    "name": "测试并发修改"
  }
}

并发修改失败

{
  "error" : {
    "root_cause" : [
      {
        "type" : "version_conflict_engine_exception",
        "reason" : "[1]: version conflict, required seqNo [11], primary term [1]. current document has seqNo [12] and primary term [1]",
        "index_uuid" : "7WEF5qaKTAaNGBLCkwx8xQ",
        "shard" : "0",
        "index" : "es_test"
      }
    ],
    "type" : "version_conflict_engine_exception",
    "reason" : "[1]: version conflict, required seqNo [11], primary term [1]. current document has seqNo [12] and primary term [1]",
    "index_uuid" : "7WEF5qaKTAaNGBLCkwx8xQ",
    "shard" : "0",
    "index" : "es_test"
  },
  "status" : 409
}

删除文档

格式: DELETE /索引名称/_doc/id

DELETE /es_db/_doc/1

查询文档

1. 根据id查询文档,格式: GET /索引名称/_doc/id

get /es_test/_doc/1

2. 条件查询 _search 格式:/索引名称/_doc/_search

get /es_test/_search
{
}

ES Search API提供了两种条件查询搜索方式:

    1. REST风格的请求URI,直接将参数带过去
    1. 封装到request body中,这种方式可以定义更加易读的JSON格式

REST风格的请求URI,直接将参数带过去

通过URI搜索,使用“q”指定查询字符串,“query string syntax” KV键值对

  1. 条件查询, 如要查询age等于28岁的 _search?q=*:***
    GET /es_test/_doc/_search?q=age:28

  2. 范围查询, 如要查询age在25至26岁之间的 _search?q=***[** TO **] 注意: TO 必须为大写
    GET /es_test/_doc/_search?q=age[25 TO 26]

  3. 查询年龄小于等于28岁的 :<=
    GET /es_test/_doc/_search?q=age:<=28

  4. 查询年龄大于28前的 :>
    GET /es_test/_doc/_search?q=age:>28

  5. 分页查询 from=*&size=*
    GET /es_test/_doc/_search?q=age[25 TO 26]&from=0&size=1

  6. 对查询结果只输出某些字段 _source=字段,字段
    GET /es_test/_doc/_search?_source=name,age

  7. 对查询结果排序 sort=字段:desc/asc
    GET /es_test/_doc/_search?sort=age:desc

GET /es_test/_doc/_search?q=age[28 TO 35]&from=0&size=2&_source=name,age&sort=age:desc

{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [
      {
        "_index" : "es_test",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : null,
        "_source" : {
          "name" : "测试并发修改",
          "age" : 35
        },
        "sort" : [
          35
        ]
      },
      {
        "_index" : "es_test",
        "_type" : "_doc",
        "_id" : "6",
        "_score" : null,
        "_source" : {
          "name" : "赵虎",
          "age" : 32
        },
        "sort" : [
          32
        ]
      }
    ]
  }
}

通过请求体的搜索方式会在后面课程详细讲解(DSL)

GET /es_test/_search
{
  "query": {
    "match": {
      "address": "广州白云"
    }
  }
}

ElasticSearch文档批量操作

  • 支持在一次API调用中,对不同的索引进行操作
  • 可以在URI中指定Index,也可以在请求的Payload中进行
  • 操作中单条操作失败,并不会影响其他操作
  • 返回结果包括了每一条操作执行的结果

批量写入

批量对文档进行写操作是通过_bulk的API来实现的

  • 请求方式:POST
  • 请求地址:_bulk
  • 请求参数:通过_bulk操作文档,一般至少有两行参数(或偶数行参数)
  • 第一行参数为指定操作的类型及操作的对象(index,type和id)
  • 第二行参数才是操作的数据
{"actionName":{"_index":"indexName", "_type":"typeName","_id":"id"}}
{"field1":"value1", "field2":"value2"}

actionName:表示操作类型,主要有create,index,delete和update

1. 批量创建文档create

POST _bulk
{"create":{"_index":"article", "_type":"_doc", "_id":3}}
{"id":3,"title":"fox老师","content":"fox老师666","tags":["java", "面向对象"],"create_time":1554015482530}
{"create":{"_index":"article", "_type":"_doc", "_id":4}}
{"id":4,"title":"mark老师","content":"mark老师NB","tags":["java", "面向对象"],"create_time":1554015482530}

2. 普通创建或全量替换index

如果原文档不存在,则是创建
如果原文档存在,则是替换(全量修改原文档)

POST _bulk
{"index":{"_index":"article", "_type":"_doc", "_id":3}}
{"id":3,"title":"图灵徐庶老师","content":"图灵学院徐庶老师666","tags":["java", "面向对象"],"create_time":1554015482530}
{"index":{"_index":"article", "_type":"_doc", "_id":4}}
{"id":4,"title":"图灵诸葛老师","content":"图灵学院诸葛老师NB","tags":["java", "面向对象"],"create_time":1554015482530}

3. 批量删除delete

POST _bulk
{"delete":{"_index":"article", "_type":"_doc", "_id":3}}
{"delete":{"_index":"article", "_type":"_doc", "_id":4}}

4. 批量修改update

POST _bulk
{"update":{"_index":"article", "_type":"_doc", "_id":3}}
{"doc":{"title":"ES大法必修内功"}}
{"update":{"_index":"article", "_type":"_doc", "_id":4}}
{"doc":{"create_time":1554018421008}}

5. 组合应用

POST _bulk
{"create":{"_index":"article", "_type":"_doc", "_id":3}}
{"id":3,"title":"fox老师","content":"fox老师666","tags":["java", "面向对象"],"create_time":1554015482530}
{"delete":{"_index":"article", "_type":"_doc", "_id":3}}
{"update":{"_index":"article", "_type":"_doc", "_id":4}}
{"doc":{"create_time":1554018421008}}

批量读取

es的批量查询可以使用mget和msearch两种
mget是需要我们知道它的id,可以指定不同的index,也可以指定返回值source
msearch可以通过字段查询来进行一个批量的查找。

_mget

1. 通过ID批量获取不同index和type的数据, 异常的会返回
GET _mget
{
  "docs": [
    {
      "_index": "es_test",
      "_id": 1
    },
    {
      "_index": "article",
      "_id": 4
    }
  ]
}
response
{
  "docs" : [
    {
      "_index" : "es_test",
      "_type" : "_doc",
      "_id" : "1",
      "_version" : 5,
      "_seq_no" : 12,
      "_primary_term" : 1,
      "found" : true,
      "_source" : {
        "address" : "广州天河公园",
        "sex" : 1,
        "name" : "测试并发修改",
        "remark" : "java developer",
        "age" : 35
      }
    },
    {
      "_index" : "article",
      "_type" : null,
      "_id" : "4",
      "error" : {
        "root_cause" : [
          {
            "type" : "index_not_found_exception",
            "reason" : "no such index [article]",
            "resource.type" : "index_expression",
            "resource.id" : "article",
            "index_uuid" : "_na_",
            "index" : "article"
          }
        ],
        "type" : "index_not_found_exception",
        "reason" : "no such index [article]",
        "resource.type" : "index_expression",
        "resource.id" : "article",
        "index_uuid" : "_na_",
        "index" : "article"
      }
    }
  ]
}

2.通过ID批量获取es_test的数据
GET /es_test/_mget
{
  "docs": [
    {
      "_id": 1
    },
    {
      "_id": 10
    }
  ]
}
response
{
  "docs" : [
    {
      "_index" : "es_test",
      "_type" : "_doc",
      "_id" : "1",
      "_version" : 5,
      "_seq_no" : 12,
      "_primary_term" : 1,
      "found" : true,
      "_source" : {
        "address" : "广州天河公园",
        "sex" : 1,
        "name" : "测试并发修改",
        "remark" : "java developer",
        "age" : 35
      }
    },
    {
      "_index" : "es_test",
      "_type" : "_doc",
      "_id" : "10",
      "found" : false
    }
  ]
}
3.通过ID批量获取es_test的数据
GET /es_test/_mget 
{
 "ids":["1","10"]  
 }

_msearch

_msearch中,请求格式和bulk类似。查询一条数据需要两个对象,第一个设置index和type,第二个设置查询语句。查询语句和search相同。如果只是查询一个index,我们可以在url中带上index,这样,如果查该index可以直接用空对象表示

GET /es_test/_msearch
{}
{"query" : {"match_all" : {}}, "from" : 0, "size" : 2}
{"index" : "es_goods"}
{"query" : {"match_all" : {}}}

response
{
  "took" : 0,
  "responses" : [
    {
      "took" : 0,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 8,
          "relation" : "eq"
        },
        "max_score" : 1.0,
        "hits" : [
          {
            "_index" : "es_test",
            "_type" : "_doc",
            "_id" : "2",
            "_score" : 1.0,
            "_source" : {
              "name" : "李四",
              "sex" : 1,
              "age" : 28,
              "address" : "广州荔湾大厦",
              "remark" : "java assistant"
            }
          },
          {
            "_index" : "es_test",
            "_type" : "_doc",
            "_id" : "3",
            "_score" : 1.0,
            "_source" : {
              "name" : "王五",
              "sex" : 0,
              "age" : 26,
              "address" : "广州白云山公园",
              "remark" : "php developer"
            }
          }
        ]
      },
      "status" : 200
    },
    {
      "took" : 0,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 2,
          "relation" : "eq"
        },
        "max_score" : 1.0,
        "hits" : [
          {
            "_index" : "es_goods",
            "_type" : "_doc",
            "_id" : "1",
            "_score" : 1.0,
            "_source" : {
              "proId" : "2",
              "name" : "牛仔男外套",
              "desc" : "牛仔外套男装春季衣服男春装夹克修身休闲男生潮牌工装潮流头号青年春秋棒球服男 7705浅蓝常规 XL",
              "timestamp" : 1576313264451,
              "createTime" : "2019-12-13 12:56:56"
            }
          },
          {
            "_index" : "es_goods",
            "_type" : "_doc",
            "_id" : "2",
            "_score" : 1.0,
            "_source" : {
              "proId" : "6",
              "name" : "HLA海澜之家牛仔裤男",
              "desc" : "HLA海澜之家牛仔裤男2019时尚有型舒适HKNAD3E109A 牛仔蓝(A9)175/82A(32)",
              "timestamp" : 1576314265571,
              "createTime" : "2019-12-18 15:56:56"
            }
          }
        ]
      },
      "status" : 200
    }
  ]
}

初始化数据

PUT /es_test/_doc/1
{
"name": "张三",
"sex": 1,
"age": 25,
"address": "广州天河公园",
"remark": "java developer"
}
PUT /es_test/_doc/2
{
"name": "李四",
"sex": 1,
"age": 28,
"address": "广州荔湾大厦",
"remark": "java assistant"
}

PUT /es_test/_doc/3
{
"name": "王五",
"sex": 0,
"age": 26,
"address": "广州白云山公园",
"remark": "php developer"
}

PUT /es_test/_doc/4
{
"name": "赵六",
"sex": 0,
"age": 22,
"address": "长沙橘子洲",
"remark": "python assistant"
}

PUT /es_test/_doc/5
{
"name": "张龙",
"sex": 0,
"age": 19,
"address": "长沙麓谷企业广场",
"remark": "java architect assistant"
}   
    
PUT /es_test/_doc/6
{
"name": "赵虎",
"sex": 1,
"age": 32,
"address": "长沙麓谷兴工国际产业园",
"remark": "java architect"
}
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐