elasticSearch7-3.2-restApi

es7-3.2 restApi

    • 一、elasticSearch7-3.2 restApi
      • 1、自动建库的方式
      • 2、 手动建库(推荐)
      • 3、增删改查
      • 4、常用数据类型
      • 5、GET
      • 6、DELETE
      • 7、UPDATE
      • 8、复杂查询
    • 二、elasticSearch7 版本的控制
      • 2.1 routing
      • 2.4 version_type

一、elasticSearch7-3.2 restApi

1、自动建库的方式

PUT /索引名/_doc/文档id
文档内容 json 串

这种方式虽然方便, 但是在后面进行term索引的时候, 会有一定的问题. 
因为这种默认的方式, 并不会进行ik分词
可以通过 GET /lisen 来看一下索引库结构:

elasticSearch7-3.2-restApi_第1张图片


2、 手动建库(推荐)

#建表语句, img, price 都是默认的, title进行了ik分词处理, 否则在查询的时候, 对中文不是很支持
PUT /jd_goods
{
  "mappings": {
    "properties" : {
        "img" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "price" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "title" : {
          "type" : "text",
          "analyzer": "ik_max_word"
        }
      }
  }
}

3、增删改查

#PUT    索引名/_doc/文档id    创建文档-指定id
#POST   索引名/_doc     创建文档-随机id
#POST   索引名/_update/文档id   修改文档
#DELETE 索引名/_doc/文档id     删除文档
#GET    索引名/_doc/文档id     通过id获取文档
#POST   索引名/_search    查询所有数据

4、常用数据类型

#字符串类型  text  keyword
#数值类型 long integer short byte double float, half float, scaled float
#日期类型 data
#布尔类型 boolean
#二进制类型  binary
PUT /lisen/_doc/1
{
  "name":"elvin",
  "age": 29,
  "work": "java软件开发工程师",
  "hobby":["篮球", "羽毛球", "乒乓球", "游泳"],
  "desc": "一个喜欢运动, 爱老婆的boy"
}

PUT /lisen/_doc/2
{
  "name":"john",
  "age": 27,
  "work": "前端开发工程师",
  "hobby":["骑电瓶车", "羽毛球"],
  "desc": "一个很刚的帅小伙"
}

PUT /lisen/_doc/3
{
  "name":"sury",
  "age": 35,
  "work": "测试工程师",
  "hobby":["带娃", "乒乓球"],
  "desc": "一个很有想法的小伙"
}

PUT /lisen/_doc/4
{
  "name":"主公",
  "age": 35,
  "work": "测试工程师",
  "hobby":["带饭", "游泳"],
  "desc": "一个摇摆不定的小伙"
}

5、GET

GET /库名 
可以获取建库信息

elasticSearch7-3.2-restApi_第2张图片

GET /库名/_doc/文档id
根据文档id获取信息, 相当于 select * from 库名 where id = #{id}

elasticSearch7-3.2-restApi_第3张图片

6、DELETE

DELETE /库名
直接删索引库, 删除之后, 再 get 就回报错

get/

elasticSearch7-3.2-restApi_第4张图片

DELETE /库名/_doc/文档id
根据文档id进行删除

elasticSearch7-3.2-restApi_第5张图片

7、UPDATE

1) PUT方式修改 - 全量修改
2) POST方式修改 - 可以全量, 也可以非全量

PUT /库名/_doc/文档id
PUT 在 restFull 里面代表两个意思: add 和 update, 当没有id时, 新增, 当有id时修改
在这里, 也是一样的. 当有指定的id时, 修改, 当没有指定的id时, 新增这是一种全量修改方式

elasticSearch7-3.2-restApi_第6张图片

POST /库名/_doc/文档id
这也是一种全量方式, 结果和 PUT 是一样的. 同样的, post也可以新增数据.

POST /库名/_update/文档id
非全量方式, 他只有修改的功能, 没有新增文档的功能

如果只有全量方式, 那岂不是很不方便. 

elasticSearch7-3.2-restApi_第7张图片

8、复杂查询

复杂查询可以实现 分页, 排序, 高亮, 模糊查询, 精确查询
查询有两种方式, 一种是拼参的方式, 另一种是 GET /库名/_search{} 的方式

elasticSearch7-3.2-restApi_第8张图片

GET /库名/_search
#_source显示那些列
可以直接写数组,:  ["name", "age", "work", "hobby", "desc"]
还可以设置 includes 和 excludes,:

#sort 排序
对字段进行排序,:
"_source": 
  {
    "includes": ["name", "age", "work", "hobby", "desc"],
    "excludes": ["work", "hobby"]
  }

"sort": [
    {
      "age": {
        "order": "desc"
      }
    }
  ]
分页
#from 相当于pageNo
#size 相当于pageSize, 默认20

将上面组合起来, 查询看看:

sc"],
“excludes”: [“work”, “hobby”]
}

“sort”: [
{
“age”: {
“order”: “desc”
}
}
]


~~~java
分页
#from 相当于pageNo
#size 相当于pageSize, 默认20

将上面组合起来, 查询看看:

elasticSearch7-3.2-restApi_第9张图片

二、elasticSearch7 版本的控制

2.1 routing

在生产环境,一个index是被分为多个各分片的,路由机制和分片机制密切相关。
举例有一个index,它被分3个分片,每个分片各有一个副本。	
	主分片P0,P1,P2
	副分片R0,R1,R2

在index数据不指定routing时,ES默认用文档的ID来作为路由计算值,计算公式如下:
shard = hash(routing) % number_of_primary_shards
1-number_of_primary_shards是主分片数,这里就是3。对文档ID进行hash,再除以3,得到的余数肯定是012之间的数,对应主分片P0,P1,P2。这样起到了负载均衡的效果,使得每个分片里文档的数量理想情况下是几乎一样的。

举例ID=”abc“,shard = hash(“abc”) % 3 = 2,则把文档存到分片P2上。

3.1.1 根据文档ID查找
举例ID=”abc“,shard = hash(“abc”) % 3 = 2,则把这次查询发往分片P2上,因为插入时,ID=“abc”的数据就存在分片2上。这样就解释了index一旦创建好,主分片参数number_of_primary_shards是不能修改的,如果后期修改了它,查询时计算出的分片号和存入时分片号就不一致了。

3.1.2 自定义路由
如果不是根据文档ID查找,而是根据别的查询条件找,那默认是把请求发给所有的分片上,然后把每个分片的查询结果在协调节点上聚合,然后再给客户端最终结果。想想如果分片数很多,这样是很消耗系统系能的。
如果我们存数据时指定了路由routing参数,查询数据时也指定相同的routing参数,这样就会发给那一个分片,这样提高了查询效率,不用给每个分片发请求了。

PUT /pigg/_doc/100?routing=dept1
{
  "name": "winter",
  "dept": "dept1"
}

PUT /pigg/_doc/101?routing=dept1
{
  "name": "dong",
  "dept": "dept1"
}

查询时指定routing
GET /pigg/_search?routing=dept1
{
  "query": {
    "term": {
      "dept.keyword": {
        "value": "dept1"
      }
    }
  }
}
注意使用routing时,这个和业务数据是相关联的,一定要考虑到业务数据的特性。
例如routing=dept1的有10万条,routing=dept2的数据只有1千条,那么10万条数据在一个分片上,1千条数据在另一个分片上,这样导致了数据倾斜。

3.2 timeout
当index操作时,可能主分片不可用,例如此时主分片正在恢复中,或在重定向。这个时候index操作就得等待主分片可用,默认这个等待时间是1分钟,当然也可以自定义。

等待主分片10秒
PUT /pigg/_doc/102?timeout=10s
{
  "name": "dong2",
  "dept": "dept1"
}
3.3 refresh
刚学ES时,都知道ES是一个近实时系统,写入的数据要约1秒后才能查询到。
refresh可以设置3种值,指定刷新行为。
ES的JavaAPI里定义了refresh的枚举如下:

public static enum RefreshPolicy implements Writeable {
    NONE("false"),
    IMMEDIATE("true"),
    WAIT_UNTIL("wait_for");
    //省略别的代码
}
它有falsetrue,wait_for三个值,ES默认是false。

(1)refresh = false
index后,不进行相关刷新操作,等待一定时间(1),修改的数据可被查询到,ES默认这个。
(2)refresh = true

index后,立即刷新相关的主碎片和副本碎片(不是整个索引),以便可以立即搜索到修改后的文档。这样看着挺好,但是有不足的,否则ES也不会默认1S后可查询了。
如果频率的执行refresh=true的操作,会生成很多小的段文件,这也会给后期段文件的合并增加处理时间,因而会影响搜索效率,这样就得不偿失。
这个要谨慎考虑设置为true。
(3)refresh = wait_for
wait_for顾名思义,就是等待请求所做的更改被刷新可见。
对于在生产环境中,一般还是使用默认的配置refresh = false,很少有理由去设置refresh为别的,在技术选型时用ES了,也就得考虑到ES只是近实时,不是完全实时的。

3.3 version
每个文档都有一个版本号version,新增后version=1,以后每次修改,version自动加1,也可以指定version,比如让它从1一下子变成10这样。

#先新增一个ID=100的文档
PUT /pigg/_doc/100
{
  "name": "三爷"
}

#返回结果如下,注意这个版本号_version=1
{
  "_index" : "pigg",
  "_type" : "_doc",
  "_id" : "100",
  "_version" : 1,//注意这个版本号
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 1,
  "_primary_term" : 1
}
但我们要修改文档前,我们已经知道当前version=1,如果文档被别人修改过,那version肯定大于1。
当我们要修改时,带上version参数(值是我们认定的更新前,当前文档的version值),如果我们指定的与ES里文档相等,则能成功,否则报异常。

#指定跟新前文档现有version=1
PUT /pigg/_doc/100?version=1
{
  "name": "三爷2"
}

#因为中间没有别人操作过id=100的文档,所以修改成功,version变成2
{
  "_index" : "pigg",
  "_type" : "_doc",
  "_id" : "100",
  "_version" : 2,
  "result" : "updated",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 2,
  "_primary_term" : 1
}

3.5 if_seq_no & if_primary_term
ES是乐观并发控制的,在ES6.7这个版本之前是用version+version_type,现在新版本的ES用if_seq_no & if_primary_term在做并发控制。
seq_no不是属于当个文档,它是属于整个index,这个和version不同,version是每个文档修改后都+1,每个文档的version相互不影响。
_primary_term表示文档所在主分片的编号
但是每个文档依旧有自己的seq_no值,更新一个文档时,还是用该文档的seq_no控制并发。
seq_no属于整个index,当index中任何文档修改或新增,seq_no都会+1。
	例如id=1的文档创建后,seq_no=1,
		那么id=2的文档创建后,seq_no=2,
		再然后id=1的文档修改后,seq_no=3
		再对id=2的文档修改,要并发控制,if_seq_no得=21)创建文档获取_seq_no和_primary_term
	PUT pigg/_doc/300
	{
	  "name": "winter"
	}
返回结果如下,注意看最后2个_seq_no和_primary_term
	{
	  "_index" : "pigg",
	  "_type" : "_doc",
	  "_id" : "300",
	  "_version" : 1,
	  "result" : "created",
	  "_shards" : {
	    "total" : 2,
	    "successful" : 1,
	    "failed" : 0
	  },
	  "_seq_no" : 13,
	  "_primary_term" : 1
	}2)修改时带上if_seq_no&if_primary_term
	PUT pigg/_doc/300?if_seq_no=13&if_primary_term=1
	{
	  "name": "winter1"
	}
返回结果可见_seq_no加1{
	  "_index" : "pigg",
	  "_type" : "_doc",
	  "_id" : "300",
	  "_version" : 2,
	  "result" : "updated",
	  "_shards" : {
	    "total" : 2,
	    "successful" : 1,
	    "failed" : 0
	  },
	  "_seq_no" : 14,//从13变成14了
	  "_primary_term" : 1
	}3)模拟并发操作
再次执行相同的操作
更新时,指定序列号,如果序列号相同进行更新,不同则报错
PUT pigg/_doc/300?if_seq_no=13&if_primary_term=1
	{
	  "name": "winter1"
	}
返回报错,说seqNo已经是14{
	  "error" : {
	    "root_cause" : [
	      {
	        "type" : "version_conflict_engine_exception",
	        "reason" : "[300]: version conflict, required seqNo [13], primary term [1]. current document has seqNo [14] and primary term [1]",
	        "index_uuid" : "1EcXaVewTu2IFK_4OAGxIw",
	        "shard" : "0",
	        "index" : "pigg"
	      }
	    ],
	    "type" : "version_conflict_engine_exception",
	    "reason" : "[300]: version conflict, required seqNo [13], primary term [1]. current document has seqNo [14] and primary term [1]",
	    "index_uuid" : "1EcXaVewTu2IFK_4OAGxIw",
	    "shard" : "0",
	    "index" : "pigg"
	  },
	  "status" : 409
	}

2.4 version_type

  • 在指定version参数时,我们还可以指定version_type参数。它有3种类型
    elasticSearch7-3.2-restApi_第10张图片
#指定了version_type=external,必须version>当前的version
PUT /pigg/_doc/100?version=10&version_type=external
{
  "name": "三爷3"
}

#返回结果如下,version变成指定的10
{
  "_index" : "pigg",
  "_type" : "_doc",
  "_id" : "100",
  "_version" : 10,
  "result" : "updated",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 4,
  "_primary_term" : 1
}

你可能感兴趣的:(ES,java)