文档 (就类似于MySQL中一个表的一条条数据)
之前说elasticsearch是面向文档的,那么意味着索引和搜索数据的最小单位是文档,elasticsearch中,文档有几个重要属性:
- 自我包含,一篇文档同时包含字段和对应的值,也就是同时包含keyralue!
可以是层次型的,一个文档中包含自文档,复杂的逻辑实体就是这么来的!(就是一个JSON对象,FastJson进行转换!) - 灵活的结构,文档不依赖预先定义的模式,我们知道关系型数据库中,要提前定义字段才能使用,在elasticsearch中,对于字段是非常灵活的,有时候,我们可以忽略该字段,或者动态的添加一个新的字段。
- 尽管我们可以随意的新增或者忽略某个字段,但是,每个字段的类型非常重要,比如一个年龄字段类型,可以是字符串也可以是整形。因为elasticsearch会保存字段和类型之间的映射及其他的设置,这种映射具体到每个映射的每种类型,这也是为什么在elasticsearch中,类型有时候也称为映射类型。
类型
类型是文档的逻輯容器,就像关系型数据库一样,表格是行的容器。类型中对于字段的定义称为映射,比如name映射为字符串类型。我们说文档是无模式的,它们不需要拥有映射中所定义的所有字段,比如新增一个字段,那么 elasticsearch是怎么做的呢?
elasticsearch会自动的将新字段加入映射,但是这个字段的不确定它是什么类型, elasticsearch就开始猜,如果这个值是18,那么elasticsearch会认为它是整形,但是 elasticsearch也可能猜不对,所以最安全的方式就是提前定义好所需要的映射,这点跟关系型数据库殊途同归了,先定义好字段,然后再使用,别整什么幺蛾子
索引
可以对比为数据库!
索引是腴射类型的容器, elasticsearch中的索引是一个非常大的文档集合,索引存储了映射类型的字段和其他设置。然后它们被存储到了各个分片上了。我们来研究下分片是如何工作的
物理设计:节点和分片如何工作
一个集群至少有一个节点,而一个节点就是一个 elasricsearch进程,节点可以有多个索引默认的,如果你创建索引,那么索引将会有个5个分片( primary shard又称主分片)构成的,每个主分片会有一个副本( replica shard,又称复制分片)
上图是一个有3个节点的集群,可以看到主分片和对应的复制分片都不会在同一个节点内,这样有利于某个节点挂掉了,数据也不至于丢失。实际上,一个分片是一个 Lucene索引,一个包含倒排索引的文件目录,倒排索引的结构使得 elasticsearch在不扫描全部文档的情况下,就能告诉你哪些文档包含特定的关键字。不过,等等,倒排索引是什么鬼?
倒排索引
elasticsearch使用的是一种称为倒排索引的结构,采用 Lucene倒排索作为底层。这种结构适用于快速的全文搜索,一个索引由文档中所有不重复的列表构成,对于每一个词,都有一个包含它的文档列表。
倒排索引原理
索引的字段类型
字符串类型:text、keyword
数值类型:long、integer、short、byte、double、float、half float、scaled、float
日期类型:date
布尔值类型:boolean
二进制类型:binary
ik分词器
分为 最小分词器:ik_smart和最细粒度划分:ik_max_word
如果分词器中的查询字典不够用了 可以在ik的config文件夹下新建自己的字典
例如:xxxx.dic 然后在IKAnalyzer.cfg.xml 文件中 配置自己的配置文件,以;分隔开。最后重启es;
请求es使用restful风格,es的restful风格比较特殊
通常http协议里面的四种操作为
GET用来获取资源,
POST用来新建资源,
PUT用来更新资源,
DELETE用来删除资源。
而es中
常用命令
#创建索引和插入数据 也可用于强制更新数据 但是如果字段不全 没有的字段自动设为空
PUT /wudw/wudw01/1
{
"name": "wudw",
"age": 23,
"gerder": "man"
}
PUT /wudw/wudw01/1
{
"name": "wudw",
"age": 24,
"desc": "cool"
}
PUT /wudw/wudw01/1
{
"name": "cmc",
"age": 23,
"gerder": "woman"
}
PUT /wudw/wudw01/1
{
"name": "cmc",
"age": 24,
"desc": "beautiful"
}
#创建索引 设置字段类型
PUT /wudw02
{
"mappings":
{
"properties":
{
"name":
{
"type": "text"
},
"age":
{
"type": "integer"
},
"birthday":
{
"type": "date"
}
}
}
}
#获取数据
GET /wudw/wudw01/1
#获取索引类型
GET /wudw02
#查看底层信息
GET _cat/indices?v
#修改数据-------推荐------
POST /wudw/wudw01/1/_update
{"doc":{
"name": "cmc",
"age": 23,
"gerder": "man"
}
}
#删除数据
DELETE /wudw/wudw01/1
# 根据条件查询用户
# 所有用户得分(权重)相同
GET wudw/wudw01/_search?q=name:wudw
#递归查询
GET /wudw/wudw01/_search
{
"query": {
"match": {
"name": "wudw"
}
}
}
#结果过滤
GET /wudw/wudw01/_search
{
"query": {
"match": {
"name": "wudw"
}
},
"_source": ["name","desc"]
}
# 排序,分数消失
GET /wudw/wudw01/_search
{
"query": {
"match": {
"name": "wudw"
}
},
"sort": [{
"age": {
"order": "desc"
}
}]
}
# 多条件查询,must相当于and,should相当于or,must_not相当于not,结果为4条数据
GET /wudw/wudw01/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"name": "wudw"
}
},
{
"match": {
"name": "cmc"
}
}
]
}
}
}
# 分页,from和size相当于limit的两个参数
GET /wudw/wudw01/_search
{
"query": {
"match": {
"name": "wudw"
}
},
"sort": [{
"age": {
"order": "desc"
}
}],
"from": 0,
"size": 1
}
#should相当于or,结果为1条数据
GET /wudw/wudw01/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "wudw"
}
},
{
"match": {
"age": "23"
}
}
]
}
}
}
#结果为name!=wudw and age!=23的那条数据
GET /wudw/wudw01/_search
{
"query": {
"bool": {
"must_not": [
{
"match": {
"name": "wudw"
}
},
{
"match": {
"age": "23"
}
}
]
}
}
}
# 过滤查询,gt和gte相当于>和>=,lt和lte相当于<和<=
GET /wudw/wudw01/_search
{
"query": {
"bool": {
"filter": {
"range": {
"age": {
"gt": 23,
"lte": 24
}
}
}
}
}
}
# 多条件查询,用空格隔开,满足一个条件即可
GET /wudw/wudw01/_search
{
"query": {
"match": {
"name": "wudw cmc"
}
}
}
#选出所有满足条件的
GET /hotel/_search
{
"query": {
"multi_match": {
"query": "外滩如家",
"fields": ["name","brand"]
}
}
}
#精确匹配
GET /hotel/_search
{
"query": {
"term": {
"city": {
"value": "上海"
}
}
}
}
#改变排名权重
GET /hotel/_search
{
"query": {
"function_score": {
"query": {
"match": {
"name": "外滩"
}
},
"functions": [
{
"filter": {
"term": {
"brand": "如家"
}
},
"weight": 10
}
],
"boost_mode": "multiply"
}
}
}
#查询名字带有”如家“ 价格不高于400,在坐标31.21,121.5周围10km范围内的酒店。。。。 注意:must_not和filter不参与排名算score
GET /hotel/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "如家"
}
}
],
"filter": {
"geo_distance": {
"distance": "10km",
"location": {
"lat": 31.21,
"lon": 121.5
}
}
},
"must_not": [
{
"range": {
"price": {
"gt": 400
}
}
}
]
}
}
}
#默认情况搜索字段 需要与高亮字段一致
GET /hotel/_search
{
"query": {
"multi_match": {
"query": "外滩如家",
"fields": ["name","brand"]
}
},
"highlight": {
"fields": {
"name": {
"pre_tags": "<wu>",
"post_tags": "</wu>"
}
}
}
}
结果:如下
term 查询直接通过倒排索引指定的词条进行精确查找。
text 类型会被分词器解析,keyword 类型不会被分词器解析。
es节点职责划分:
查询结果:
1. 默认hash运算 节点位置=hash(_route)%分片数量
2. 分片数量一旦创建后,不能再修改了
如果不是根据id查询呢 那就是通过路由节点将请求分发到每个节点上,最后还由路由节点汇总结果返回。