Elasticsearch基础概念和查询请求的使用

标签:

本文出自jvm123.com-java技术分享站:http://jvm123.com/2019/10/elasticsearch.html

ElasticSearch是一个基于Lucene的搜索服务器,也是一个数据存储服务器,可使用RESTful web接口进行操作查询。

基本概念

  1. 索引: 相当于数据库
  2. 类型: 相当于数据表
  3. 文档: 相当于记录(使用json格式存储的记录),文档中的包含若干个字段

一个完整的文档如下:

      {
        "_index": "es_test",
        "_type": "user",
        "_id": "0",
        "_version": 1,
        "_source": {
          "id": 0,
          "name": "yawn",
          "age": 12,
          "des": "我是一个小学生,我唉学习。"
        }
      }

文档中的元数据metadata

es中数据是以文档的形式存储的,类似于mongodb,每一个文档都有以下metadata:

  • _index 表示所在的索引,需要提前创建好索引
  • _type 表示文档的类型,需要在前面创建好类型
  • _id 文档的id,可以指定或者自动生成

所以,每一个文档都可以使用_index、 _type、 _id 唯一确定。

_version 乐观锁版本控制

在java的集合中,常常会有modCount字段,也就是fail-fast机制:在线程不安全的集合中,如果使用迭代器的过程中,发现集合被修改,会抛出ConcurrentModificationExceptions错误,这就是fail-fast机制。对集合进行结构性修改时,modCount都会增加,在初始化迭代器时,modCount的值会赋给expectedModCount,在迭代的过程中,只要modCount改变了,int expectedModCount == modCount等式就不成立了,迭代器检测到这一点,就会抛出错误:currentModificationExceptions。

es乐观锁的版本控制也类似,乐观并发控制如下:

Elasticsearch是分布式的。当文档被创建、更新或删除,文档的新版本会被复制到集群的其它节点。Elasticsearch的这些复制请求都是平行发送的,无序到达目的地。这就需要一种方法确保老版本的文档永远不会覆盖新的版本。

发送index、get、delete请求时,每个文档都有一个_version号码,这个号码在文档被改变时加一。Elasticsearch使用这个_version保证所有修改都被正确排序。当一个旧版本出现在新版本之后,它会被简单的忽略。

Elasticsearch 服务的端口

es中启动后,暴露两个端口,默认是9200和9300。9200是我们发送http请求进行查询等操作的端口;9300是es集群之间进行通信的tcp端口,spring data jpa 连接es时,使用的是9300tcp端口,所以它并不是通过http请求来操作Elasticsearch。

Elasticsearch RESTFul接口操作

在restful风格的请求中,get表示获取数据,post表示新增数据,put表示修改数据,delete表示删除数据,所以,es请求操作有如下的请求方式。

put添加:

PUT /{index}/{type}/{id}
{
  "field": "value",
  ...
}

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

post添加:

POST /website/blog/
{
  "title": "My second blog entry",
  "text":  "Still trying this out...",
  "date":  "2014/01/01"
}

创建一个文档,还可以使用如下请求:

 PUT /website/blog/123?op_type=create
 { … }
 或
 PUT /website/blog/123/_create
 { … }
 如果返回409,则表示文档已经存在,本次创建失败
 如果返回201,则表示创建成功

get查询:

GET /website/blog/123?pretty
如果加了pretty参数,返回的json格式就是经过格式化的,否则不会格式化

GET /website/blog/123?_source=title,text
只查询title和text字段

GET /website/blog/123/_source
只查询_source,不回返回其他的元数据,返回结果如下:
{
   "title": "My first blog entry",
   "text":  "Just trying this out...",
   "date":  "2014/01/01"
}

检查文档是否存在,还是使用get查询的请求:
GET /website/blog/123
返回的http状态吗如果是404则表示不存在,200表示存在

put更新:

PUT /website/blog/123
{
  "title": "My first blog entry",
  "text":  "I am starting to get the hang of this...",
  "date":  "2014/01/02"
}

更新还是使用put请求,需要指定index/type/id,版本号会自增1

delete删除:

DELETE /website/blog/123
指定文档的index/type/id就可以删除了
如果返回404,表示这个文档本来就不存在
200表示删除成功

post文档局部更新:

POST /website/blog/1/_update
{
   "doc" : {
      "tags" : [ "testing" ],
      "views": 0
   }
}
doc中有两个字段,文档中已有的字段tags将会被替换,没有的字段views将会被添加到原有的文档中,结果如下:
{
   "_index":    "website",
   "_type":     "blog",
   "_id":       "1",
   "_version":  3,
   "found":     true,
   "_source": {
      "title":  "My first blog entry",
      "text":   "Starting to get the hang of this...",
      "tags": [ "testing" ],
      "views":  0
   }
}

post使用groovy脚本进行局部更新:

POST /website/blog/1/_update
{
   "script" : "ctx._source.views+=1"
}

POST /website/blog/1/_update
{
   "script" : "ctx._source.tags+=new_tag",
   "params" : {
      "new_tag" : "search"
   }
}

POST /website/blog/1/_update
{
   "script" : "ctx.op = ctx._source.views == count ? 'delete' : 'none'",
    "params" : {
        "count": 1
    }
}

ctx._source在脚本中表示文档的内容。

更新可能不存在的文档使用upsert,就会被创建
POST /website/pageviews/1/_update
{
   "script" : "ctx._source.views+=1",
   "upsert": {
       "views": 1
   }
}

mget查询多种类型的文档:

POST /_mget
{
   "docs" : [
      {
         "_index" : "website",
         "_type" :  "blog",
         "_id" :    2
      },
      {
         "_index" : "website",
         "_type" :  "pageviews",
         "_id" :    1,
         "_source": "views"
      }
   ]
}
返回结构一样的文档,"_source"有内容

如果你想检索的文档在同一个_index中(甚至在同一个_type中),你就可以在URL中定义一个默认的/_index或者/_index/_type
POST /website/blog/_mget
{
   "docs" : [
      { "_id" : 2 },
      { "_type" : "pageviews", "_id" :   1 }
   ]
}
POST /website/blog/_mget
{
   "ids" : [ "2", "1" ]
}

bulk批量更新操作:

POST /_bulk
{ "delete": { "_index": "website", "_type": "blog", "_id": "123" }} <delete没有请求体>
{ "create": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "title":    "My first blog post" }
{ "index":  { "_index": "website", "_type": "blog" }}
{ "title":    "My second blog post" }
{ "update": { "_index": "website", "_type": "blog", "_id": "123", "_retry_on_conflict" : 3} }
{ "doc" : {"title" : "My updated blog post"} } <请求体>

POST /website/_bulk
{ "index": { "_type": "log" }}
{ "event": "User logged in" }

POST /website/log/_bulk
{ "index": {}}
{ "event": "User logged in" }
{ "index": { "_type": "blog" }}
{ "title": "Overriding the default type" }

有一个最佳的bulk请求大小。超过这个大小,性能不再提升而且可能降低。一个好的批次最好保持在5-15MB大小间。

请求有以下action:
create	当文档不存在时创建之。详见《创建文档》
index	创建新文档或替换已有文档。见《索引文档》和《更新文档》
update	局部更新文档。见《局部更新》
delete	删除一个文档。见《删除文档》

_search端点查询:

GET /index/type/_search

GET /index/type/_search?q=name:yagao&sort=price:desc

_search的DSL查询:

GET /index/type/_search
{
  // 请求体中位查询参数
}

eg: 查询所有
{
  "query":{
    "match_all": {

     }
  }
}
eg:查询匹配字段
{
  "query":{
    "matchc": {
        "name": "yawn"
     }
  }
}
eg: 分页查询
{
  "query": {
    "match_all": {}
  },
  "from":1,   //从第几条开始    (从0开始)
  "size":1      //大小
}

eg: 排序
{
    "query": {
       "match_all": {}
    },
    "sort": [
        {
            "FIELD": {
                "order": "desc"
            }
        }
    ]
}
eg: 返回指定字段
{
  "query": {
    "match_all": {}
  },
  "_source": ["name","price"],
  "from":1,
  "size":1
}
eg: 过滤器(查询完成后的过滤)
{
    "query": {
        "bool": {
            "must": {
                "match":{
                    "name":"yagao"
                }
            },
            "filter" : {
                "range" : {
                    "price" : { "gt" : 6 }     //价格大于6的
                }
            }
        }
    }
}
eg: 短语搜索
{
    "query" : {
        "match_phrase": {
          "des": "宝马"
        }
    }
}
eg: 高亮显示
{
    "query" : {
        "match" : {
            "producer" : "producer"
        }
    },
    "highlight": {     //高亮显示
        "fields" : {    //字段
            "producer" : {}
        }
    }
}

发表评论