ES=elaticsearch简写, Elasticsearch是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理PB级别的数据。 本质上是一个分布式nosql数据库,允许多台服务器协同工作,每台服务器可以运行多个 Elastic 实例。单个 Elastic 实例称为一个节点(node)。一组节点构成一个集群(cluster)。
关系数据库(mysql) ⇒ 数据库 ⇒ 表 ⇒ 行 ⇒ 列(Columns)
Elasticsearch ⇒ 索引 ⇒ 类型 ⇒ 文档 ⇒ 字段(Fields)
存储在Elasticsearch中的主要实体叫文档(document)。用关系型数据库来类比的话,一个文档相当于数据库表中的一行记录。文档由多个字段组成,每个字段可能多次出现在一个文档里,这样的字段叫多值字段(multivalued)。每个字段有类型,如文本、数值、日期等。字段类型也可以是复杂类型,一个字段包含其他子文档或者数组。字段类型在Elasticsearch中很重要,因为它给出了各种操作(如分析或排序)如何被执行的信息。幸好,这可以自动确定,然而,我们仍然建议使用映射。与关系型数据库不同,文档不需要有固定的结构,每个文档可以有不同的字段。从客户端的角度看,文档是一个JSON对象。每个文档存储在一个索引中,并有一个Elasticsearch自动生成的唯一标识符和文档类型。文档需要有对应文档类型的唯一标识符,这意味着在一个索引中,两个不同类型的文档可以有相同的唯一标识符。
ElasticSearch 客户端程序除了Java 使用TCP的方式连接ES集群以外,其他的语言基本上都是使用的Http的方式。众所周知,ES 客户端默认的TCP端口为9300,而HTTP默认端口为9200。elasticsearch-hadoop 使用的就是HTTP的方式连接的ES集群。
Mapping)相当于数据表的表结构。ElasticSearch中的映射(Mapping)用来定义一个文档,可以定义所包含的字段以及字段的类型、分词器及属性等等,映射可以分为动态映射和静态映射。
(1)动态映射
我们知道,在关系数据库中,需要事先创建数据库,然后在该数据库实例下创建数据表,然后才能在该数据表中插入数据。而ElasticSearch中不需要事先定义映射(Mapping),文档写入ElasticSearch时,会根据文档字段自动识别类型,这种机制称之为动态映射。
注意:不建议使用动态mapping,因为Elasticsearch的动态Mapping并不总是精确的。动态Mapping对于
入门很有用
,但在某些时候您需要结合业务数据指定Mapping。
(2)静态映射
当然,在ElasticSearch中也可以事先定义好映射,包含文档的各个字段及其类型等,这种方式称之为静态映射。
我们已经知道Elasticsearch把数据存储在一个或多个索引上,每个索引包含各种类型的文档。我们也知道了每个文档有很多字段,映射定义了Elasticsearch如何对待这些字段。但还有更多,从一开始,Elasticsearch就被设计为能处理数以亿计的文档和每秒数以百计的搜索请求的分布式解决方案。这归功于几个重要的概念,我们现在将更详细地描述。
一个集群是由一个或多个ES节点组成的集合
每一个集群都有一个唯一的名字
每一个节点都是通过集群的名字来加入集群的
每一个节点都有自己的名字
节点能够存储数据,参与集群索引数据以及搜索数据的独立服务
“倒排索引”是Lucene用于使数据可搜索的数据结构。一图胜千言!如下:索引、分片、分段的关系
一目了然,一个index多个shard(分片),一个shard多个segment。
为了防止elasticsearch宕机造成数据丢失保证可靠存储,es会将每次写入数据同时写到translog日志中。translog还用于提供实时CRUD。 当您尝试按ID检索,更新或删除文档时,它会首先检查translog中是否有任何最近的更改,然后再尝试从相关段中检索文档。 这意味着它始终可以实时访问最新的已知文档版本。TransLog作为事务日志,记录了所有写入信息。因为Lucene缓存中的数据默认1秒之后才生成segment文件,即使是生成了segment文件,这个segment是写到页面缓存中的,并不是实时的写到磁盘,只有达到一定时间或者达到一定的量才会强制flush磁盘。如果这期间机器宕掉,内存中的数据就丢了。如果发生这种情况,内存中的数据是可以从TransLog中进行恢复的,TransLog默认是每5秒都会刷新一次磁盘。但这依然不能保证数据安全,因为仍然有可能最多丢失TransLog中5秒的数据。这里可以通过配置增加TransLog刷磁盘的频率来增加数据可靠性,最小可配置100ms,但不建议这么做,因为这会对性能有非常大的影响。一般情况下,Elasticsearch是通过副本机制来解决这一问题的。即使主分片所在节点宕机,丢失了5秒数据,依然是可以通过副本来进行恢复的
相比于Lucene的提交操作,ES的refresh是相对轻量级的操作。先将index-buffer中文档(document)生成的segment写到文件系统之中,这样避免了比较损耗性能io操作,又可以使搜索可见。默认1s钟刷新一次,所以说ES是近实时的搜索引擎,不是准实时。
注意:实际需要结合自己的业务场景设置refresh频率值。调大了会优化索引速度。注意单位:s代表秒级。
PUT /my_logs
{
"settings": {
"refresh_interval": "30s"
}
}
es中创建后的mapping不可修改,但是可以添加新字段
添加新字段:
PUT /my_index/_mapping/my_type
{
"properties": {
"new_field_name": {
"type": "string"
}
}
}
赋值:
POST my_index/_update_by_query
{
"script": {
"lang": "painless",
"inline": "ctx._source.new_field_name= '02'"
}
}
注意 默认生成的mapping都是下面这种,默认值是text,可以.keyword转化成keyword类型
"properties": {
"DstIp": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
在任意的查询字符串中增加pretty参数,会让Elasticsearch美化输出(pretty-print)JSON响应以便更加容易阅读。
_source字段不会被美化,它的样子与我们输入的一致。
ES数据结构
在ES中原始的文本会存储在_source里面(除非你关闭了它)。默认情况下其他提取出来的字段都不是独立存储的,是从_source里面提取出来的。当然你也可以独立的存储某个字段,只要设置store:true即可。独立存储某个字段,在频繁使用某个特殊字段时很常用。而且获取独立存储的字段要比从_source中解析快得多,而且额外你还需要从_source中解析出来这个字段,尤其是_source特别大的时候。不过需要注意的是,独立存储的字段越多,那么索引就越大;索引越大,索引和检索的过程就会越慢....
string
字符串类型,es中最常用的类类型: 注意:5.X以上版本没有string类型了,换成了text
把string字段设置为了过时字段,引入text,keyword字段,这两个字段都可以存储字符串使用,但建立索引和搜索的时候是不太一样的
keyword:存储数据时候,不会分词建立索引
text:存储数据时候自动分词并生成索引(这是智能的,但在有些字段里面是没用的,所以对于有些字段使用text则浪费了空间)
store存储
true 独立存储 false(默认)不存储,从_source中解析
Numeric
数值类型,注意numeric并不是一个类型,它包括多种类型,比如:long,integer,short,byte,double,float,每种的存储空间都是不一样的,一般默认推荐integer和float。官方文档参考
重要的参数:
index分析 not_analyzed(默认) ,设置为该值可以保证该字段能通过检索查询到
store存储 true 独立存储 false(默认)不存储,从_source中解析
date
日期类型,该类型可以接受一些常见的日期表达方式,官方文档参考。
重要的参数:
index分析 not_analyzed(默认) ,设置为该值可以保证该字段能通过检索查询到
store存储 true 独立存储 false(默认)不存储,从_source中解析
format格式化
strict_date_optional_time||epoch_millis(默认)
你也可以自定义格式化内容,比如
"date": {
"type": "date",
"format": "yyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}
boolean
布尔类型,所有的类型都可以标识布尔类型,参考官方文档
False: 表示该值的有:false, "false", "off", "no", "0", "" (empty string), 0, 0.0
True: 所有非False的都是true
重要的参数:
index分析 not_analyzed(默认) ,设置为该值可以保证该字段能通过检索查询到
store存储 true 独立存储 false(默认)不存储,从_source中解析
我讲从索引(数据库)→类型(表)→文档(行)→属性(字段)一一介绍相关的指令
Http请求内容:
PUT /customer?pretty
GET /_cat/indices?v
Curl命令
curl -XPUT ‘localhost:9200/customer?pretty&pretty’
curl -XGET ‘localhost:9200/_cat/indices?v&pretty’
x_pack加密后 我们可以在命令中添加 --user username:password 指定用户和密码
curl -X ://:/? -d ''
VERB HTTP方法:GET, POST, PUT, HEAD, DELETE
POST不用加具体的id,它是作用在一个集合资源之上的(/uri),而PUT操作是作用在一个具体资源之上的(/uri/xxx)。
在ES中,如果不确定document的ID(documents具体含义见下),那么直接使用POST对应uri( “POST /website/blog” ),ES可以自己生成不会发生碰撞的UUID当做ID;如果确定document的ID,即自己设置的ID,使用PUT即可,比如 “PUT /website/blog/123”,那么执行创建或修改(修改时_version版本号提高1)
curl -H "Content-Type: application/json" 'localhost:9200/_mapping?pretty=true'
curl -XPUT 'localhost:9200/sqlcommand?pretty'
或 5.5 以后尽量使用下面的方式
curl -XPUT -H 'Content-Type: application/json' 'localhost:9200/megacorp?pretty'(5.5以后版本)
返回信息 代表创建成功
{
"acknowledged" : true,
"shards_acknowledged" : true
}
curl -XGET -H 'Content-Type: application/json' 'localhost:9200/_cat/indices?v'
curl -XDELETE 'localhost:9200/sqlcommand?pretty'
curl -H "Content-Type: application/json" -PUT "http://127.0.0.1:9200/sqltest/infotest/_mapping?pretty" -d '
{
"infotest": {
"properties": {
"application_id": {
"type": "keyword"
},
"session_id": {
"type": "keyword"
},
"user_ip_address": {
"type": "keyword"
},
"logger_type": {
"type": "keyword"
},
"mryxblg_command_monitoring": {
"type": "keyword"
}
}
}
}'
导入数据
curl -H "Content-Type: application/json" -XPOST 'http://127.0.0.1:9200/productx/product/1' -d '
{
"title": "物品",
"description": "电脑",
"price": 89.0
"onSale": true
"type": 2
"createDate": 2018
}'
注意:PUT一定要大写 -d之前,必需要空格
查看索引的type
curl -X GET 'localhost:9200/sql_command/_mapping'
GET /my_index_name/_mapping
GET /my_index_name/_settings
GET /test/_segments
PUT /my_logs
{
"settings": {
"refresh_interval": "30s"
}
}
新创建的document数据会先进入到index buffer之后,与此同时会将操作记录在translog之中,当发生refresh时ranslog中的操作记录并不会被清除,而是当数据从filesystem cache中被写入磁盘之后才会将translog中清空。
从filesystem cache写入磁盘的过程就是flush。
flush操作如下:
POST /_flush?wait_for_ongoing
普通检索
curl -XGET -H 'Content-Type: application/json' 'http://localhost:9200/megacorp/employee/1'
轻量检索
curl -XGET -H 'Content-Type: application/json' 'http://localhost:9200/megacorp/employee/_search'
检索部分内容
curl -XGET -H 'Content-Type: application/json' 'http://localhost:9200/megacorp/employee/1?_source=first_name,last_name'
只得到源的内容
curl -XGET -H 'Content-Type: application/json' 'http://localhost:9200/megacorp/employee/1?_source'
按条件搜索
curl -XGET -H 'Content-Type: application/json' 'http://localhost:9200/megacorp/employee/_search?q=last_name:Smith'
Q =表示匹配全部文档 * 排序=年龄表示按照年龄信息排序 ASC表示升序
注意:这个不是咱一般的准确查询,查出来的是模糊查询,不是title=elasticsearch,而是包含这个词,就返回。
curl -XGET 'localhost:9200/megacorp/_search?pretty'
使用检索表达式
curl -XGET -H 'Content-Type: application/json' 'http://localhost:9200/megacorp/employee/_search?pretty' -d '
{
"query" : {
"match" : {
"last_name" : "Smith"
}
}
}'
复杂检索
curl -XGET -H 'Content-Type: application/json' 'http://localhost:9200/megacorp/employee/_search?pretty' -d '
{
"query" : {
"bool": {
"must": {
"match" : {
"last_name" : "smith"
}
},
"filter": {
"range" : {
"age" : { "gt" : 30 }
}
}
}
}
}'
批量检索(multi-get或者mget API)
mget API要求有一个docs数组作为参数,每个元素包含需要检索文档的元数据,包括_index,_type和_id。如果你想检索一个或者多个特定的字段,那么你可以通过_source参数来指定这些字段的名字:
curl -XGET -H 'Content-Type: application/json' 'http://localhost:9200/_mget?pretty' -d '
{
"docs" : [
{
"_index" : "megacorp",
"_type" : "employee",
"_id" : 2
},
{
"_index" : "megacorp",
"_type" : "employee",
"_id" : 1
}
]
}'
如果想检索的数据都在相同的_index中(甚至相同的_type中),则可以在URL中指定默认的/ _index或者默认的
curl -i -XHEAD -H 'Content-Type: application/json' 'http://localhost:9200/megacorp/employee/4'
curl -XDELETE -H 'Content-Type: application/json' 'http://localhost:9200/megacorp/employee/4'
成功返回200,找不到是404,版本会加1(即使是虚假),_版本值仍然会增加。这是Elasticsearch内部记录本的一部分,用来确保这些改变在跨多节点时以正确的顺序执行)
删除全部文档
curl -XPOST -H 'Content-Type: application/json' 'http://localhost:9200/megacorp/employee/_delete_by_query?conflicts=proceed' -d '
{
"query": {
"match_all": {}
}
}'
GET /sql_command_flink/sqldata/_search
{
"query": {
"wildcard": {
"current_time": {
"value": "*2019*"
}
}
}
}
假设您只想匹配以W开头,紧跟着数字的邮政编码。使用regexp查询能够让你写下更复杂的模式:
GET /my_index/address/_search
{
"query": {
"regexp": {
"postcode": "W[0-9].+"
}
}
}
这个正则表达式的规定了词条需要以W开头,紧跟着一个0到9的数字,然后是一个或者多个其它字符。
下面例子是所有以 wxopen 开头的正则
{
"query": {
"regexp": {
"hostname": "wxopen.*"
}
}
}
match查询是一个标准查询,不管你需要全文本查询还是精确查询基本上都要用到它。如果你使用 match 查询一个全文本字段,它会在真正查询之前用分析器先分析match一下查询字符:
{
"match": {
"tweet": "About Search"
}
}
主意:libary是索引名 使用时 其他不用变
curl -X POST "127.0.0.1:9200/_xpack/sql/translate" -H 'Content-Type: application/json' -d'
{
"query": "SELECT * FROM library ORDER BY page_count DESC",
"fetch_size": 10
}
'
扫一扫加入大数据技术交流群,了解更多大数据技术,还有免费资料等你哦
扫一扫加入大数据技术交流群,了解更多大数据技术,还有免费资料等你哦
扫一扫加入大数据技术交流群,了解更多大数据技术,还有免费资料等你哦