1.文档

在Elasticsearch中,文档以JSON格式进行存储,可以是复杂的结构,如:

  1. {
  2. "_index": "haoke",
  3. "_type": "user",
  4. "_id": "1005",
  5. "_version": 1,
  6. "_score": 1,
  7. "_source": {
  8. "id": 1005,
  9. "name": "孙七",
  10. "age": 37,
  11. "sex": "女",
  12. "card": {
  13. "card_number": "123456789,
  14. }
  15. }
  16. }

其中,card是一个复杂对象,嵌套的Card对象。

元数据(metadata)

节点 说明
_index 文档存储的地方
_type 文档代表的对象的类
_id 文档的唯一标识

_index
索引(index)类似于关系型数据库里的“数据库”——它是我们存储和索引关联数据的地方.
PS: 事实上,我们的数据被存储和索引在分片(shards)中,索引只是一个把一个或多个分片分组在一起的逻辑空间。然而,这只是一些内部细节——我们的程序完全不用关心分片。对于我们的程序而言,文档存储在索引(index)中。剩下的细节由Elasticsearch关心既可。
_type
在应用中,我们使用对象表示一些“事物”,例如一个用户、一篇博客、一个评论,或者一封邮件。每个对象都属于一个类(class),这个类定义了属性或与对象关联的数据。 user 类的对象可能包含姓名、性别、年龄和Email地址。
在关系型数据库中,我们经常将相同类的对象存储在一个表里,因为它们有着相同的结构。同理,在Elasticsearch中,我们使用相同类型(type)的文档表示相同的“事物”,因为他们的数据结构也是相同的。
每个类型(type)都有自己的映射(mapping)或者结构定义,就像传统数据库表中的列一样。所有类型下的文档被存储在同一个索引下,但是类型的映射(mapping)会告诉Elasticsearch不同的文档如何被索引。
_type 的名字可以是大写或小写,不能包含下划线或逗号。我们将使用 blog 做为类型名
_id
id仅仅是一个字符串,它与 _index 和 _type 组合时,就可以在Elasticsearch中唯一标识一个文档。当创建一个文档,你可以自定义 _id ,也可以让Elasticsearch帮你自动生成(32位长度)

2.查询相应

pretty

可以在查询url后面添加pretty参数,使得返回的json更易查看
http://192.168.249.134:9200/haoke/user/2001?pretty
05 核心详细 - 图1

指定响应字段

在响应的数据中,如果我们不需要全部的字段,可以指定某些需要的字段进行返回。

  1. GET /haoke/user/2001?_source=id,name
  2. # 响应结果:
  3. {
  4. "_index": "haoke",
  5. "_type": "user",
  6. "_id": "2001",
  7. "_version": 3,
  8. "found": true,
  9. "_source": {
  10. "name": "索隆"
  11. }
  12. }

如不需要返回元数据,仅仅返回原始数据,可以这样:

  1. GET /haoke/user/2001/_source
  2. # 响应结果:
  3. {
  4. "name": "索隆",
  5. "age": 53,
  6. "qq": 65745154352,
  7. "sex": "male"
  8. }

还可以这样:

  1. GET /haoke/user/2001/_source?_source=name,age
  2. # 响应结果:
  3. {
  4. "name": "索隆",
  5. "age": 53
  6. }

3.判断文档是否存在

  1. HEAD /haoke/user/2001
  2. # 返回:
  3. 200 - OK
  4. HEAD /haoke/user/不存在的id
  5. # 返回:
  6. 404 - Not Found

4.批量操作

有些情况下可以通过批量操作以减少网络请求。如:批量查询、批量插入数据。

批量查询

  1. GET /haoke/user/_mget
  2. {
  3. "ids":["2001","2002"]
  4. }

05 核心详细 - 图2
如果,某一条数据不存在,不影响整体响应,需要通过found的值进行判断是否查询到数据。

  1. GET /haoke/user/_mget
  2. {
  3. "ids":["2001","666"]
  4. }

05 核心详细 - 图3

_bulk操作

在Elasticsearch中,支持批量的插入、修改、删除操作,都是通过_bulk的api完成的。
请求格式如下:(请求格式不同寻常)

  1. { action: { metadata }}\n
  2. { request body }\n
  3. { action: { metadata }}\n
  4. { request body }\n
  5. ...
  1. POST /haoke/user/_bulk
  2. {"create":{"_index":"haoke","_type":"user","_id":2004}}
  3. {"id":2004,"name":"name1","age":"20","sex":"remale"}
  4. {"create":{"_index":"haoke","_type":"user","_id":2005}}
  5. {"id":2005,"name":"name2","age":"40","sex":"male"}
  6. {"create":{"_index":"haoke","_type":"user","_id":2006}}
  7. {"id":2006,"name":"name3","age":"50","sex":"male"}

05 核心详细 - 图4

  1. POST/haoke/user/_bulk
  2. {"delete":{"_index":"haoke","_type":"user","_id":2004}}
  3. {"delete":{"_index":"haoke","_type":"user","_id":2005}}
  4. {"delete":{"_index":"haoke","_type":"user","_id":2006}}

由于delete没有请求题,所以action后直接写下一行
05 核心详细 - 图5

  1. POST /haoke/user/_bulk
  2. {"update":{"_index":"haoke","_type":"user","_id":2004}}
  3. {"doc":{"name":"updateName"}}

一次请求多少性能最高?
● 整个批量请求需要被加载到接受我们请求节点的内存里,所以请求越大,给其它请求可用的内存就越小。有一个最佳的bulk请求大小。超过这个大小,性能不再提升而且可能降低。
● 最佳大小,当然并不是一个固定的数字。它完全取决于你的硬件、你文档的大小和复杂度以及索引和搜索的负载。
● 幸运的是,这个最佳点(sweetspot)还是容易找到的:试着批量索引标准的文档,随着大小的增长,当性能开始降低,说明你每个批次的大小太大了。开始的数量可以在1000~5000个文档之间,如果你的文档非常大,可以使用较小的批次。
● 通常着眼于你请求批次的物理大小是非常有用的。一千个1kB的文档和一千个1MB的文档大不相同。一个好的批次最好保持在5-15MB大小间

5.分页

  1. size: 结果数,默认10
  2. from: 跳过开始的结果数,默认0
  1. GET haoke/user/_search?size=5
  2. GET haoke/user/_search?size=5&from=5
  3. GET haoke/user/_search?size=5&from=10

6.映射

前面我们创建的索引以及插入数据,都是由Elasticsearch进行自动判断类型,有些时候我们是需要进行明确字段类型的,否则,自动判断的类型和实际需求是不相符的。
自动判断的规则如下:

JSON type Field type
Boolean: true or false “boolean”
Whole number: 123 “long”
Floating point: 123.45 “double”
String, valid date: “2014-09-15” “date”
String: “foo bar” “string”

Elasticsearch中支持的类型如下:

类型 表示的数据类型
String string , text , keyword
Whole number byte , short , integer , long
Floating point float , double
Boolean boolean
Date date

● string类型在ElasticSearch 旧版本中使用较多,从ElasticSearch 5.x开始不再支持string,由text和keyword类型替代。
● text 类型,当一个字段是要被全文搜索的,比如Email内容、产品描述,应该使用text类型。设置text类型以后,字段内容会被分析,在生成倒排索引以前,字符串会被分析器分成一个一个词项。text类型的字段不用于排序,很少用于聚合。
● keyword类型适用于索引结构化的字段,比如email地址、主机名、状态码和标签。如果字段需要进行过滤(比如查找已发布博客中status属性为published的文章)、排序、聚合。keyword类型的字段只能通过精确值搜索到。
创建明确类型的索引:

  1. PUT /itcast/
  2. {
  3. "settings": {
  4. "index": {
  5. "number_of_shards": "2",
  6. "number_of_replicas": "0"
  7. }
  8. },
  9. "mappings": {
  10. "person": {
  11. "properties": {
  12. "name": {
  13. "type": "text"
  14. },
  15. "age": {
  16. "type": "integer"
  17. },
  18. "mail": {
  19. "type": "keyword"
  20. },
  21. "hobby": {
  22. "type": "text"
  23. }
  24. }
  25. }
  26. }
  27. }

查看映射:

  1. GET /itcast/_mapping
  2. # 返回:
  3. {
  4. "itcast": {
  5. "mappings": {
  6. "person": {
  7. "properties": {
  8. "age": {
  9. "type": "integer"
  10. },
  11. "hobby": {
  12. "type": "text"
  13. },
  14. "mail": {
  15. "type": "keyword"
  16. },
  17. "name": {
  18. "type": "text"
  19. }
  20. }
  21. }
  22. }
  23. }
  24. }

插入测试数据:

  1. POST /itcast/_bulk
  2. {"index":{"_index":"itcast","_type":"person"}}
  3. {"name":"张三","age":20,"mail":"111@qq.com","hobby":"羽毛球、乒乓球、足球"}
  4. {"index":{"_index":"itcast","_type":"person"}}
  5. {"name":"李四","age":21,"mail":"222@qq.com","hobby":"羽毛球、乒乓球、足球、篮球"}
  6. {"index":{"_index":"itcast","_type":"person"}}
  7. {"name":"王五","age":22,"mail":"333@qq.com","hobby":"羽毛球、篮球、游泳、听音乐"}
  8. {"index":{"_index":"itcast","_type":"person"}}
  9. {"name":"赵六","age":23,"mail":"444@qq.com","hobby":"跑步、游泳"}
  10. {"index":{"_index":"itcast","_type":"person"}}
  11. {"name":"孙七","age":24,"mail":"555@qq.com","hobby":"听音乐、看电影"}

05 核心详细 - 图6

  1. POST /itcast/person/_search
  2. {
  3. "query": {
  4. "match": {
  5. "hobby": "音乐"
  6. }
  7. }
  8. }

05 核心详细 - 图7

7.结构化查询

1) term查询

term 主要用于精确匹配哪些值,比如数字,日期,布尔值或 not_analyzed 的字符串(未经分析的文本数据类型):

  1. POST /itcast/person/_search
  2. {
  3. "query": {
  4. "term": {
  5. "age": 20
  6. }
  7. }
  8. }

05 核心详细 - 图8

2) terms查询

terms 跟 term 有点类似,但 terms 允许指定多个匹配条件。 如果某个字段指定了多个值,那么文档需要一起去做匹配:

  1. POST /itcast/person/_search
  2. {
  3. "query": {
  4. "terms": {
  5. "age": [20,21]
  6. }
  7. }
  8. }

05 核心详细 - 图9

3) range查询

range过滤允许我们按照指定范围查找一批数据:
gt :: 大于
gte :: 大于等于
lt :: 小于
lte :: 小于等于

  1. POST /itcast/person/_search
  2. {
  3. "query": {
  4. "range": {
  5. "age": {
  6. "gte": 22,
  7. "lt": 24
  8. }
  9. }
  10. }
  11. }

05 核心详细 - 图10

4) exists查询

exists 查询可以用于查找文档中是否包含指定字段或没有某个字段,类似于SQL语句中的 IS_NULL 条件

  1. POST /haoke/user/_search
  2. {
  3. "query": {
  4. "exists":{ # 必须包含
  5. "field":"qq"
  6. }
  7. }
  8. }

05 核心详细 - 图11
05 核心详细 - 图12

5) match查询

match 查询是一个标准查询,不管你需要全文本查询还是精确查询基本上都要用到它。
如果你使用 match 查询一个全文本字段,它会在真正查询之前用分析器先分析 match 一下查询字符:

  1. {
  2. "match": {
  3. "tweet": "About Search"
  4. }
  5. }

如果用 match 下指定了一个确切值,在遇到数字,日期,布尔值或者 not_analyzed 的字符串时,它将为你搜索你给定的值:

  1. { "match": { "age": 26 }}
  2. { "match": { "date": "2014-09-01" }}
  3. { "match": { "public": true }}
  4. { "match": { "tag": "full_text" }}

6) bool查询

bool 查询可以用来合并多个条件查询结果的布尔逻辑,它包含一下操作符:
must :: 多个查询条件的完全匹配,相当于 and 。
must_not :: 多个查询条件的相反匹配,相当于 not 。
should :: 至少有一个查询条件匹配, 相当于 or 。
这些参数可以分别继承一个查询条件或者一个查询条件的数组:

  1. POST /itcast/person/_search
  2. {
  3. "query": {
  4. "bool": {
  5. "must": {
  6. "term": {
  7. "folder": "inbox"
  8. }
  9. },
  10. "must_not": {
  11. "term": {
  12. "tag": "spam"
  13. }
  14. },
  15. "should": [
  16. {
  17. "term": {
  18. "starred": true
  19. }
  20. },
  21. {
  22. "term": {
  23. "unread": true
  24. }
  25. }
  26. ]
  27. }
  28. }
  29. }

8.过滤查询

前面讲过结构化查询,Elasticsearch也支持过滤查询,如term、range、match等。
示例:查询年龄为20岁的用户

  1. POST /itcast/person/_search
  2. {
  3. "query": {
  4. "bool": {
  5. "filter": {
  6. "term": {
  7. "age": 20
  8. }
  9. }
  10. }
  11. }
  12. }

● 一条过滤语句会询问每个文档的字段值是否包含着特定值。
● 查询语句会询问每个文档的字段值与特定值的匹配程度如何。
一条查询语句会计算每个文档与查询语句的相关性,会给出一个相关性评分 _score,并且 按照 相关性对匹配到的文档进行排序。 这种评分方式非常适用于一个没有完全配置结果的全文本搜索。
●一个简单的文档列表,快速匹配运算并存入内存是十分方便的, 每个文档仅需要1个字节。这些缓存的过滤结果集与后续请求的结合使用是非常高效的。
● 查询语句不仅要查找相匹配的文档,还需要计算每个文档的相关性,所以一般来说查询语句要比 过滤语句更耗时,并且查询结果也不可缓存

4.中文分词