elasticsearch

elasticsearch背景 https://www.cnblogs.com/Neeo/p/10304892.html

我们建立一个网站或应用程序,并要添加搜索功能,但是想要完成搜索工作的创建是非常困难的。我们希望搜索解决方案要运行速度快,我们希望能有一个零配置和一个完全免费的搜索模式,我们希望能够简单地使用JSON通过HTTP来索引数据,我们希望我们的搜索服务器始终可用,我们希望能够从一台开始并扩展到数百台,我们要实时搜索,我们要简单的多租户,我们希望建立一个云的解决方案。因此我们利用Elasticsearch来解决所有这些问题及可能出现的更多其它问题。

什么是elasticsearch?

 一个搜素服务器,它提供了一个分布式多用户能力的全文搜索引擎,也可以说是一个数据库.基于RESTful web接口,也可以作为数据库使用。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

elasticsearch特点

  • 分布式实时文档存储,并将每一个字段都编入索引,使其可以被搜索。
  • 实时分析的分布式搜索引擎。
  • 可以扩展到上百台服务器,处理PB级别的结构化或非结构化数据。

应用场景

 可以作为一个搜素的插件应用到项目中

elasticsearch组织架构

elasticsearch中文档,类型,索引的关系

①elasticsearch是面向文档的,那么就意味着索引和搜索数据的最小单位是文档;

  • 自我包含,一篇文档同时包含字段和对应的值,也就是同时包含key:value
  • 可以是层次型的,一个文档中包含自文档,复杂的逻辑实体就是这么来的
  • 灵活的结构,文档不依赖预先定义的模式,我们知道关系型数据库中,要提前定义字段才能使用,在elasticsearch中,对于字段是非常灵活的,有时候,我们可以忽略该字段,或者动态的添加一个新的字段。
  • 文档是无模式的,也就是说,字段对应值的类型可以是不限类型的。

②类型是文档的容器,就像mysql一样,表是行的容器;

类型中对于字段的定义称为映射,比如name映射为字符串类型。

③索引是映射类型的容器,elasticsearch中的索引是一个非常大的文档集合。索引存储了映射类型的字段和其他设置。然后它们被存储到了各个分片上了。

什么是节点和分片?

一个集群包含至少一个节点,而一个节点就是一个elasticsearch进程。节点内可以有多个索引。
默认的,如果你创建一个索引,那么这个索引将会有5个分片(primary shard,又称主分片)构成,而每个分片又有一个副本(replica shard,又称复制分片),这样,就有了10个分片。如下图

上图是一个有3个节点的集群,可以看到主分片和对应的复制分片都不会在同一个节点内,这样有利于某个节点挂掉了,数据也不至于丢失。
实际上,一个分片是一个Lucene索引,一个包含倒排索引的文件目录,倒排索引的结构使得elasticsearch在不扫描全部文档的情况下,就能告诉你哪些文档包含特定的关键字。

倒排索引

elasticsearch使用的是一种称为倒排索引的结构,采用Lucene倒排索作为底层。elasticsearch将索引被分为多个分片,每份分片是一个Lucene的索引。所以一个elasticsearch索引是由多个Lucene索引组成的。这种结构适用于快速的全文搜索,一个索引由文档中所有不重复的列表构成,对于每一个词,都有一个包含它的文档列表。

如下表,进一步理解倒排索引:

学科(原始数据) 索引列表(倒排索引)
id 学科 语言 id
1 语文 语文 1,2,3
2 语文 数学 3,4
3 语文,数学    
4 数学    

MySQL,MongoDB,Elasticsearch对比

关系型数据库和非关系型数据库比对
MySQL MongoDB Elasticsearch
数据库(database) 数据库 索引(indices)
表(tables) 表(Collection) types
行(rows)  Documents Documents
字段(columns) Field Field

总结:MySQL为关系型数据库,而MongoDB,Elasticsearch为非关系型数据库,由此看出两者的特点比较明显;

elasticsearch(集群)中可以包含多个索引(数据库),每个索引中可以包含多个类型(表),每个类型下又包含多个文档(行),每个文档中又包含多个字段(列)。

物理设计 ---> elasticsearch后台是如何处理这些数据的呢?elasticsearch将每个索引划分为多个分片,每份分片又可以在集群中的不同服务器间迁移。

注意:当然,这里需要补充的是,从elasticsearch的第一个版本开始,每个文档都存储在一个索引中,并分配多个映射类型,映射类型用于表示被索引的文档或者实体的类型,但这也带来了一些问题(详情参见Removal of mapping types),导致后来在elasticsearch6.0.0版本中一个文档只能包含一个映射类型,而在7.0.0中,映射类型则将被弃用,到了8.0.0中则将完全被删除。

elasticsearch的语法

1.基本语法写法

#基本语法
#PUT创建一文档(注意大写)t1的文档
PUT t1/doc/1
{
  "name":"可可"
}

#查询t1的文档索引信息
GET t1/doc/1  
#删除索引
DELETE t1/doc/1

PUT t1/doc/2 
{
  "name":"盼盼",
  "age":20
}

GET t1    #返回t1所有的创建信息
GET _cat/indices   #查询所有文档的信息
GET t1/_settings   #查询t1的主分片和复制分片情况
GET t1/_mapping  #查看t1的映射关系结构

创建一些数据来操作操作

#是不是有种来到汉朝的感觉,没事,放松点,呵呵
PUT han/doc/1
{
    "name":"孝景帝",
    "from":"汉朝",
    "in_time":16,
    "info":"无为而治",
    "tags":["平定七国之乱","诛晁错"],
    "female":"窦太后"  
}
PUT han/doc/2
{
    "name":"孝武帝",
    "from":"汉朝",
    "in_time":54,
    "info":"以战养战",
    "tags":["罢黜百家,独尊儒术","推恩令","平定北方匈奴","丝绸之路"],
    "female":"卫子夫"  
}

PUT han/doc/3
{
    "name":"汉高祖",
    "from":"汉朝",
    "in_time":7,
    "info":"建立汉朝",
    "tags":["鸿门宴","灭秦,楚国"],
    "female":"吕雉"  
}

PUT han/doc/4
{
    "name":"卫青",
    "from":"孝武帝",
    "in_time":2,
    "title":"关内侯",
    "info":"初伐匈奴",
    "tags":["奇袭龙城"]
}

PUT han/doc/5
{
    "name":"李广",
    "in_time":1,
    "from":"孝武帝",
    "title":"飞将军",
    "info":"射石搏虎",
    "tags":["平七国吴楚联军"]
}

PUT han/doc/6
{
    "name":"霍去病",
    "from":"孝武帝",
    "in_time":3,
    "title":"骠骑校尉",
    "info":"英年早逝,封景桓侯",
    "tags":["八百铁骑,直插敌后","平定朔方,打通西域"]
}

PUT han/doc/7
{
    "name":"李广利",
    "from":"孝武帝",
    "title":"贰师将军",
    "in_time":4,
    "info":"二征大宛",
    "tags":["征服大宛"]
}
创建数据

2.结构化查询(match相关)

"""match按关键字查询"""
#match_all查询全部
GET han/doc/_search
{
  "query": {
    "match_all": {}
  }
}
#match指定字段查询,但是这样会查出来所有name字段中跟孝武帝相关的数据,列如孝景帝. GET han/doc/_search { "query": { "match": { "name":"孝武帝" } } } #单独查询某条数据match_phrase,只会查到name是'孝武帝'的数据 GET han/doc/_search { "query": { "match_phrase": { "name": "孝武帝" } } } #最左前缀查询,match_phrase_prefix,不记得字段信息了,智能匹配 GET han/doc/_search { "query": { "match_phrase_prefix": { "name": "" } } }
#多字段查询multi_match ,查到字段中含有"帝"的数据 GET han/doc/_search { "query": { "multi_match": { "query": "", "fields": ["name","title"] } } } #multi_match甚至可以match_phrase,match_phrase_prefix使用,只要指定type即可 GET han/doc/_search { "query": { "multi_match": { "query": "", "fields": ["name"], "type": "phrase" } } } GET han/doc/_search { "query": { "multi_match": { "query": "", "fields": ["name"], "type": "phrase_prefix" } } }
#排序sort

#降序
GET han/doc/_search
{
  "query": {
    "match_all": {}
  },
  "sort":[
    {
      "in_time":{
        "order":"desc"
      }
    }
    ]
}

#升序
GET han/doc/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "in_time": {
        "order": "asc"
      }
    }
  ]
}
排序语法
#过滤_source
GET han/doc/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "in_time": {
        "order": "asc"
      }
    }
  ],
  "_source": [ "from", "in_time","name"]
}
过滤 _source
#分页 from从哪开始,size:展示条数,from,size也可以为-1
GET han/doc/_search
{
  "query": {
    "match_all": {}
  },
  "from":2,
  "size":2,
  "_source": "in_time"
}
分页
#高亮 highlight
GET han/doc/_search
{
  "query": {
    "match": {
      "from":"孝武帝"
    }
  },
  "highlight":{
    "pre_tags":"<b style='color:red;'>",
    "post_tags":"</b>",
    "fields":{
      "from": {}
    }
  }
}
搜素信息 高亮
#bool查询:must(and)/should(or)/must_not(not)

#and
GET han/doc/_search
{
  "query": {
    "bool": {
      "must": [
        {"match": {
          "in_time": "1"
          }
        },
        {
        "match": {
          "from": "孝武帝"
          }  
        }
      ]
    }
  }
}

#or
GET han/doc/_search
{
  "query": {
    "bool": {
      "should": [
        {"match": {
          "from": "汉朝"
          }
        },
        {
        "match": {
          "in_time": 54
          }  
        }
      ]
    }
  }
}

#not
GET han/doc/_search
{
  "query": {
    "bool": {
      "must_not": [
        {"match": {
          "from": "孝武帝"
          }
        },
        {
        "match": {
          "in_time": 54
          }  
        }
      ]
    }
  }
}
bool查询:must,should,must_not
#查询filter:gte(大于等于) gt(大于)lt(小于)lte(小于等于)

GET han/doc/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "from": "汉朝"
          }
        }
      ],
      "filter": {
        "range": {
          "in_time": {
            "gte": 10
          }
        }
      }
    }
  }
}

#小于
GET han/doc/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "from": "汉朝"
          }
        }
      ],
      "filter": {
        "range": {
          "in_time": {
            "lt": 10
          }
        }
      }
    }
  }
}
filter查询lte,lt,gt,gte
#聚合查询:avg,sum,max,min
GET han/doc/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "my_a1": {
      "avg": {
        "field": "in_time"
      }
    }
  }
}
聚合查询 aggs
#分组
GET han/doc/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "my_group": {
      "range": {
        "field": "in_time",
        "ranges": [
          {
            "from": 20,
            "to": 60
          }
        ]
      }
    }
  }
}

#分组再聚合
GET han/doc/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "my_group": {
      "range": {
        "field": "in_time",
        "ranges": [
          {
            "from": 10,
            "to": 60
          }
        ]
      },
      "aggs": {
        "my_sum": {
          "sum": {
            "field": "in_time"
          }
        }
      }
    }
  }
}
分组查询,分组再聚合

3.映射

映射用来自定义一个文档及其包含的字段如何存储和索引的过程

例如,我们可以使用映射来定义:

  • 哪些字符串应该被视为全文字段。
  • 哪些字段包含数字、日期或者地理位置。
  • 定义日期的格式。
  • 自定义的规则,用来控制动态添加字段的的映射。
#映射mappings写法-01 dynamic没写默认为true,可以添加字段
PUT t3
{
  "mappings":{
    "doc":{
      "properties":{
        "name":{
          "type":"text"
        },
        "age":{
          "type":"long"
        }
      }
    }
  }
  
}

GET t3/_mapping

PUT t3/doc/1
{
  "name":"窦颖",
  "age":17,
  "desc":"可爱"
}

GET t3/doc/_search
{
  "query": {
    "match": {
      "age": 17
    }
  }
}

#mappings写法-02 dynamic=false 不让添加字段,但不报错
PUT t4
{
  "mappings":{
    "doc":{
      "dynamic":false,
      "properties":{
        "name":{
          "type":"text"
        },
        "age":{
          "type":"long"
        }
      }
    }
  }
  
}

GET t4/_mapping

PUT t4/doc/1
{
  "name":"",
  "age":19,
  "desc":"可ke爱"
}


#mappings写法-03 dynamic=strict 严格模式,只要添加就报错
PUT t5
{
  "mappings": {
    "doc":{
      "dynamic":"strict",
      "properties":{
        "name":{
          "type":"text"
        }
      }
    }
  }
}

GET t5/_mapping

PUT t5/doc/1
{
  "name":"coco"
}

#缺省/严格的时候不能添加字段
PUT t5/doc/2
{
  "name":"cici",
  "age":9
}
mappings自定义形式和dynamic的三种形态
#index属性,类似于模糊查询配置,有两种状态,当true,我们的自定义字段可以实现模糊查询,false则会报错

PUT t6
{
  "mappings": {
    "doc":{
      "properties":{
        "title":{
          "type":"text",
          "index":true
        },
        "content":{
          "type":"text",
          "index":false
        }
      }
    }
  }
}


PUT t6/doc/1
{
  "title":"es长路漫漫",
  "content":"py唯你作伴"
}

#报错
GET t6/doc/_search
{
  "query": {
    "match": {
      "title":"漫漫"
    }
  }
}

GET t6/doc/_search
{
  "query": {
    "match": {
      "content":"py"
    }
  }
}
mappings写法02 index
#copy_to,该属性允许我们将多个字段的值复制到组字段中,然后将组字段作为单个字段进行查询。
#copy_to写法-01
PUT t7
{
  "mappings": {
    "doc":{
      "properties":{
        "title":{
          "type":"text",
          "copy_to":"full_name"
        },
        "content":{
          "type":"text",
          "copy_to":"full_name"
        },
        "full_name":{
          "type":"text"
        }
      }
    }
  }
}

PUT t7/doc/1
{
  "title":"aa",
  "content":"bb"
}

GET t7/doc/_search
{
  "query": {
    "match": {
      "full_name": "bb"
    }
  }
}

#copy_to写法-02
PUT t8
{
  "mappings": {
    "doc":{
      "properties":{
        "title":{
          "type":"text",
          "copy_to":["full_name1","full_name2"]
        },
        "content":{
          "type":"text",
          "copy_to":"full_name"
        },
        "full_name1":{
          "type":"text"
        },
        "full_name2":{
          "type":"text"
        }
      }
    }
  }
}
mappings写法03 copy_to
#对象属性,mappings中嵌套结构写法,查询方式:info.addr
PUT t9
{
  "mappings": {
    "doc":{
      "dynamic":false,
      "properties":{
        "name":{
          "type":"text"
        },
        "age":{
          "type":"long"
        },
        "info":{
          "properties":{
            "addr":{
              "type":"text"
            },
            "tel":{
              "type":"text"
            }
          }
        }
      }   
  }
}
}


PUT t9/doc/1
{
  "name":"vov",
  "age":19,
  "info":{
    "addr":"earth",
    "tel":"no"
  }
}
  
GET t9/doc/_search
{
  "query": {
    "match": {
      "info.addr": "earth"
    }
  }
}
mappings写法04 对象属性
#settings设置,设置主,复制分片.
#number_of_shards主分片数量,默认5,number_of_replicas复制分片,默认1个

PUT w1
{
  "mappings": {
    "doc":{
      "properties":{
        "title":{
          "type":"text"
        }
      }
    }
  },
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 2
    
  }
}


GET w1
mappings写法05 settings

...待续

原文地址:https://www.cnblogs.com/CrazySheldon1/p/10771090.html