下载:https://www.elastic.co/downloads/elasticsearch
解压缩
启动(linux为: ./elasticsearch):
测试,可通过浏览器、curl、postman
1:浏览器只能执行get操作 post、delete、put? 不太行了
curl:小巧轻便的http库,dos或者terminal直接输入命令即可发送http请求
postman:建议使用
注意到,和es打交道都是通过http协议,那不管用何种语言,只需要能发送http请求就可以学习测试es了
elasticsearch和mysql一样,也是存储数据的,先看下es的增删改查
新增三条数据:
PUT /user/doc/1
{
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
对应postman就是这样:
还挺麻烦是不是,上图最下面的是返回结果哦,再新增两条数据:
PUT /user/doc/2
{
"first_name" : "Jane",
"last_name" : "Smith",
"age" : 32,
"about" : "I like to collect rock albums",
"interests": [ "music" ]
}
PUT /user/doc/3
{
"first_name" : "Douglas",
"last_name" : "Fir",
"age" : 35,
"about": "I like to build cabinets",
"interests": [ "forestry" ]
}
注意到插入都是put请求
目前我们insert了3条记录,id为1、2、3,user代表索引,doc代表类型,后接一个id
mysql简单对应,es索引 == mysql库 es类型 == mysql表 es文档 == mysql行记录
es文档是什么呢?就是我们put操作传递的json,es已经不建议使用类型,所以本文所有索引下的类型都只有一个,名字为:doc
es自动生成id:put改为post,并去掉后面的id
查询:
所有的查询都是get请求,返回体的_source字段就是我们插入es的文档,_source同级的就是该文档的元数据,即此文档属于哪个索引,哪个类型,id多少,版本号多少等,url后门加上/_source后返回的结果就不包含这些元数据了
查询多个文档:
GET /user/doc/_mget
{
"ids" : [ "1", "2","3","4" ]
}
删除:把请求方式GET修改为DELETE就会删除该文档,删完后GET一下,发现es已经找不到了
为了继续测试更新,先把文档一put进去,然后我们修改文档,如年龄,再发送PUT请求,这时文档就被更新了
版本变成比之前增加了1,result也变为updated了,可以插入时返回的结果对比一下。
es的更新是把旧文档标记为删除,再新加入一个文档
更新和新建一样的,如何确保是新建而不是更新呢?下面两种方式都ok
put /user/doc/1?op_type=create
put /user/doc/1/_create
更新时如何处理并发导致的覆盖写呢?用version来做乐观锁
put /user/doc/1?version=1
若该文档已经被更新,那verision已经变成2了,上面的语句就不会更新,且返回http409的状态码
上面的都是全量更新,只更新部分字段(注意json根是doc,doc里面是字段):
post /user/doc/1?_update
{
"doc":{
"first_name" : "ted",
"height":180
}
}
部分更新和全量更新一样,都是把老文档标记为删除并插入新文档,不同之处是部分更新使用老文档来构建新文档,且减少从获取到重建索引的时间(正常的更新先get,再构建json,再put),部分更新会check版本号的哦
使用mget可以批量获取,那对应也有批量更新(最后一行后回车,加个空行):
POST /_bulk
{ "delete": { "_index": "user", "_type": "doc", "_id": "4" }}
{ "create": { "_index": "user", "_type": "doc", "_id": "5" }}
{ "title": "My first blog post" }
{ "index": { "_index": "user", "_type": "doc", "_id":"6" }}
{ "title": "My second blog post" }
{ "index": { "_index": "user", "_type": "doc" }}
{ "title": "auto create id" }
{ "update": { "_index": "user", "_type": "doc", "_id": "3", "_retry_on_conflict" : 3} }
{ "doc" : {"title" : "My updated blog post"} }
批量更新是逐个执行,不保证事务,那个做了对后面的不影响
delete:删除,后面不用跟任何
create是新建,后面跟着新建的文档json
index是(动词)索引,没有就插入,有则更新
update是更新,后面跟着更新的json,根为doc哦
crud基本都使用过了,再看看其他查询:
took:耗时(单位毫秒) 12
time_out:是否超值 false
shards:分片 总共5个 成功5个 跳过0个 失败0个
hits:命中 总共命中3个 最大分支为1 hits数组为命中的结果 每个结果包含(索引、类型、id、评分、_source)
分片是什么鬼呢?一会再看它
继续我们的查询:
加了个查询条件:
{
"query" : {
"match" : {
"last_name" : "Smith"
}
}
}
这个貌似太简单了,查询条件再复杂一点:
{
"query" : {
"bool": {
"must": {
"match" : {
"last_name" : "smith"
}
},
"filter": {
"range" : {
"age" : { "gt" : 30 }
}
}
}
}
}
和上面的对比增加了范围一个条件,为了使用范围过滤,需要外面包上filter,它代表过滤,filter外层包了bool,bool中第一个条件为什么不用match而是包了一个must呢?它就是这么规定的...
再来一个简单的query:
{
"query" : {
"match" : {
"about" : "rock climbing"
}
}
}
看一下查询结果,在about字段中,只要包含rock climbing任何一个单词就能被查询出来,且同时包含两个字符的得分更高,
啥?我需要about字段中两个字符都出现:
{
"query" : {
"match_phrase" : {
"about" : "rock climbing"
}
}
}