ElasticSearch入门及进阶实战(1) 基础入门

 

简介

什么是elasticsearch?

    elasticsearch是开源的分布式、Restfull  风格的数据搜索与分析引擎,是时下最流行的全文搜索引擎。

elasticsearch和Apache Lucene

    Apache Lucene是时下最先进、高性能、全功能的搜索引擎库,Apache Lucene原理和实现复杂。elasticsearch就是为了解决Lucene复杂性的,elasticsearch基于Lucene,使用java语言开发,对Lucene做了一层封装,提供一套简单一致的Restfull 风格API,是的全文检索更简单。

elasticsearch不仅仅是全文搜索引擎:

  • 一个分布式实时文档存储,每个字段都可以被索引和搜索。
  • 一个分布式实时分析搜索引擎。
  • 支持上百个服务节点扩展,支持PB级的结构化数据和非结构化数据。

安装运行

Windows下安装

step1 安装Kibana 下载Elasticsearch 6.2.2的zip包,并解压到指定目录,下载地址:https://www.elastic.co/cn/downloads/past-releases/elasticsearch-6-2-2
step2 安装中文分词插件,在elasticsearch-6.2.2\bin目录下执行以下命令
elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.2.2/elasticsearch-analysis-ik-6.2.2.zip
step3 启动es  运行es安装目录/bin/elasticsearch.bat
step4 安装Kibana  下载Kibana,作为访问Elasticsearch的客户端,请下载6.2.2版本的zip包,并解压到指定目录,下载地址:https://artifacts.elastic.co/downloads/kibana/kibana-6.2.2-windows-x86_64.zip
step5 启动Kibana  运行Kibana/bin/kibana.bat

linux下安装

step1 下载elasticsearch 6.4.0的docker镜像;
docker pull elasticsearch:6.4.0
step2 修改虚拟内存区域大小,否则会因为过小而无法启动;
sysctl -w vm.max_map_count=262144
step3 修改该目录的权限,使es有权访问目录
chmod 777 /mydata/elasticsearch/data/
step4 使用docker命令启动;
docker run -p 9200:9200 -p 9300:9300 --name elasticsearch \
-e "discovery.type=single-node" \
-e "cluster.name=elasticsearch" \
-v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
-v /mydata/elasticsearch/data:/usr/share/elasticsearch/data \
-d elasticsearch:6.4.0
step5 安装中文分词器IKAnalyzer,并重新启动;
docker exec -it elasticsearch /bin/bash
#此命令需要在容器中运行
#进入ES目录
docker exec -it elasticsearch /bin/bash 
elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.4.0/elasticsearch-analysis-ik-6.4.0.zip
docker restart elasticsearch
step6 访问es测试安装是否成功
http://linux服务器:9200/
step7 下载kibana 6.4.0的docker镜像
step8 docker命令启动
docker run --name kibana -p 5601:5601 \
--link elasticsearch:es \
-e "elasticsearch.hosts=http://es:9200" \
-d kibana:6.4.0
step8 访问测试安装是否成功
http://linux服务器地址:5601

Kibana是es可视化用户界面,在DevTol下可以使用es DSL语言操纵ES。

elasticsearch基本概念

全文搜索(Full-Text Search):计算机检索程序通过扫描文章每一个词,对每一个词建立索引,指明该词在文章中出现次数和位置。当用户查询时,检索程序根据事先建立的索引进行查询并返回查询结果给用户的查询方式。

倒排索引(Inverted Index):

  • 该索引表中每一项都包括一个属性值和具有该属性值的各记录的地址;
  • 该索引表不是由记录确认属性值,而是由属性值来确定记录的位置,因此成为倒排索引;
  • elasticsearch能够实现高效、快速搜索功能,正是基于倒排索引。

节点 &集群(Node & Cluster):elasticsearch本质是分布式数据库,允许多台服务器共同工作。每台服务器可以运行多个es实例,单个实例就是节点(Node),一组节点构成集群(Cluster)。

索引(Index):elasticsearch管理数据的顶层单位,Index必须小写英文命名。Index相当于关系数据库中的数据库。

文档(Document):Index中的单条记录称为Document,Document使用JSON格式表示。同一个Index下Document不要求具有相同数据结构(Scheme),但是最好保持一致,这样可以提供搜索效率。

类型(Type):

  • Document可以分组,比如Order这个Index,可以按订单状态分组,可以按订单类型分组,这个分组称为Type。
  • elasticsearch Tyoe是虚拟逻辑分组,用来过滤Document,Type相当于关系数据库中的数据表;
  • 一个Index下不同Type应该有相似结构,完全不同数据结构的数据应该建立不同Index。

文档元数据:文档元数据可以分为三部分

  • _index: 文档存放位置
  • -Type: 文档类型
  • _id: 文档唯一标识

三者可以唯一表示一个文档。

字段:Document是一个JSON数据结构,包含许多字段,每个字段都有对应值。字段相当于关系数据库中的字段。

                                                                      es和关系数据库类比图

elasticsearch入门

elasticsearch交互方式

elasticsearch提供Java API 和 Restfull API。基于Restfull API 其他语言程序可以通过9200端口和es进行通讯。

elasticsearch 请求分析

部件 说明
VERB 适当的HTTP方法或谓词:GET\PUT\DELETE\POST\HEAD。
PROTOCOL http或https(如果elasticsearch前面启用了代理)
HOST elasticsearch集群中任一节点主机名或者用localhost代表本地节点
PORT elasticsearch端口号,默认9200
PATH API终端路径(如_count将返回集群中文档数量)。PATH可能包含多个组件,例如:_cluster/stats 和 _nodes/stats/jvm
QUERY_STRING 任意可选的查询字符串参数,例如:?pretty 将格式化地输出 JSON 返回值,使其更容易阅读
BODY 一个JSON格式请求体

 

 

 

 

 

 

 

HTTP方法说明

HTTP方法 说明
GET 获取请求对象当前状态
PUT 创建一个对象
POST 改变当前对象状态
DELETE 删除一个对象
HEAD 获取对象的基础信息

 

 

 

 

 

基础命令详解

查看集群健康状态:

GET /_cat/health?v

查看节点状态:

GET /_cat/nodes?v

查看所有索引信息:

GET /_cat/indices?v

创建索引并查看;

PUT /customer
GET /_cat/indices?v

删除索引并查看:

DELETE /customer
GET /_cat/indices?v

查看文档的类型:

GET /pms/_mapping

在索引中添加文档

PUT /customer/doc/1
{
  "name": "John Doe"
}

查看索引中的文档

GET /customer/doc/1
{
  "_index": "customer",
  "_type": "doc",
  "_id": "1",
  "_version": 1,
  "found": true,
  "_source": {
    "name": "John Doe"
  }
}

修改索引中的文档:

POST /customer/doc/1/_update
{
  "doc": { "name": "Jane Doe" }
}
{
  "_index": "customer",
  "_type": "doc",
  "_id": "1",
  "_version": 2,
  "result": "updated",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 1,
  "_primary_term": 1
}
GET /customer/doc/1
{
  "_index": "customer",
  "_type": "doc",
  "_id": "1",
  "_version": 2,
  "found": true,
  "_source": {
    "name": "Jane Doe"
  }
}

删除索引中文档:

DELETE /customer/doc/1

对索引文档进行批量操作

POST /customer/doc/_bulk
{"index":{"_id":"1"}}
{"name": "John Doe" }
{"index":{"_id":"2"}}
{"name": "Jane Doe" }

数据搜索

elasticsearch提供了丰富灵活的查询语言-查询表达式(Query DSL),支持构建更加复杂和健壮的查询。

最简单的搜索,使用match_all来表示,例如搜索全部:

GET /pms/_search
{
  "query": { "match_all": {} }
}

分页搜索,from表示偏移量,从0开始,size表示每页显示的数量;

GET /pms/_search
{
  "query": { "match_all": {} },
  "from": 0,
  "size": 3
}

搜索排序,使用sort表示,例如按price字段降序排列;

GET /pms/_search
{
  "query": { "match_all": {} },
  "sort": { "price": { "order": "desc" } }
}

搜索并返回指定字段内容,使用_source表示,例如只返回nameprice两个字段内容:

GET /pms/_search
{
  "query": { "match_all": {} },
  "_source": ["name", "price"]
}

条件搜索,使用match表示匹配条件,例如搜索出price98的文档:

GET /pms/_search
{
  "query": {
    "match": {
      "price": 98
    }
  }
}

文本类型字段的条件搜索,例如搜索address字段中包含mill的文档,对比上一条搜索可以发现,对于数值类型match操作使用的是精确匹配,对于文本类型使用的是模糊匹配:

GET /pms/_search
{
  "query": {
    "match": {
      "name": "海澜之家"
    }
  },
  "_source": [
    "name",
    "subTitle"
  ]
}
{
  "took": 7,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 3,
    "max_score": 4.2882357,
    "hits": [
      {
        "_index": "pms",
        "_type": "product",
        "_id": "30",
        "_score": 4.2882357,
        "_source": {
          "subTitle": "2018夏季新品微弹舒适新款短T男生 6月6日-6月20日,满300减30,参与互动赢百元礼券,立即分享赢大奖",
          "name": "HLA海澜之家简约动物印花短袖T恤"
        }
      },
      {
        "_index": "pms",
        "_type": "product",
        "_id": "32",
        "_score": 4.2882357,
        "_source": {
          "subTitle": "HLA海澜之家短袖T恤男基础款简约圆领HNTBJ2E153A藏青(F3)175/92A(50)",
          "name": "HLA海澜之家短袖T恤男基础款"
        }
      },
      {
        "_index": "pms",
        "_type": "product",
        "_id": "31",
        "_score": 3.8090763,
        "_source": {
          "subTitle": "2018夏季新品短袖T恤男HNTBJ2E080A 蓝灰花纹80 175/92A/L80A 蓝灰花纹80 175/92A/L",
          "name": "HLA海澜之家蓝灰花纹圆领针织布短袖T恤"
        }
      }
    ]
  }
}

组合搜索

组合搜索,使用bool来进行组合,must表示同时满足,例如搜索subTitle字段中同时包含2018男生的文档;

GET /pms/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "subTitle": "2018" } },
        { "match": { "subTitle": "男生" } }
      ]
    }
  }
}

组合搜索,should表示满足其中任意一个,搜索name字段中包含HLA或者海澜之家的文档

GET /pms/_search
{
  "query": {
    "bool": {
      "should": [
        { "match": { "name": "HLA" } },
        { "match": { "name": "海澜之家" } }
      ]
    }
  }
}

组合搜索,must_not表示不同时满足,搜索subTitle字段不同时包含移动 电信的文档

GET /pms/_search
{
  "query": {
    "bool": {
      "must_not": [
        { "match": { "subTitle": "移动" } },
        { "match": { "subTitle": "电信" } }
      ]
    }
  }
}

组合搜索,must和must_not配合,搜索name包含小米subTitle不包含电信的文档

GET /pms/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "name": "小米" } }
      ],
      "must_not": [
        { "match": { "subTitle": "电信" } }
      ]
    }
  }
}

过滤搜索

使用filter来表示,比如获取price在600-1000之间的商品

GET /pms/_search
{
  "query": {
    "bool": {
      "must": { "match_all": {} },
      "filter": {
        "range": {
          "price": {
            "gte": 600,
            "lte": 1000
          }
        }
      }
    }
  }
}

搜索聚合

对搜索结果进行聚合,用aggs表示,类似sql的group by 。例如对brandName进行聚合,统计出brandName相同的数目

GET /pms/_search
{
  "size": 0,
  "aggs": {
    "group_by_brandName": {
      "terms": {
        "field": "brandName"
      }
    }
  }
}
{
  "took": 90,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 11,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "group_by_brandName": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "小米",
          "doc_count": 4
        },
        {
          "key": "海澜之家",
          "doc_count": 3
        },
        {
          "key": "NIKE",
          "doc_count": 2
        },
        {
          "key": "华为",
          "doc_count": 1
        },
        {
          "key": "苹果",
          "doc_count": 1
        }
      ]
    }
  }
}

嵌套聚合,同时聚合brandName和price,计算出brandName相同的数目和price的平均值

GET /pms/_search
{
  "size": 0,
  "aggs": {
    "group_by_brandName": {
      "terms": {
        "field": "brandName"
      },
      "aggs": {
        "average_price": {
          "avg": {
            "field": "price"
          }
        }
      }
    }
  }
}
{
  "took": 123,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 11,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "group_by_brandName": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "小米",
          "doc_count": 4,
          "average_price": {
            "value": 2461.5
          }
        },
        {
          "key": "海澜之家",
          "doc_count": 3,
          "average_price": {
            "value": 88
          }
        },
        {
          "key": "NIKE",
          "doc_count": 2,
          "average_price": {
            "value": 434
          }
        },
        {
          "key": "华为",
          "doc_count": 1,
          "average_price": {
            "value": 3788
          }
        },
        {
          "key": "苹果",
          "doc_count": 1,
          "average_price": {
            "value": 5499
          }
        }
      ]
    }
  }
}

对聚合搜索的结果进行排序

GET /pms/_search
{
  "size": 0,
  "aggs": {
    "group_by_brandName": {
      "terms": {
        "field": "brandName",
        "order": {
          "average_price": "desc"
        }
      },
      "aggs": {
        "average_price": {
          "avg": {
            "field": "price"
          }
        }
      }
    }
  }
}
{
  "took": 39,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 11,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "group_by_brandName": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "苹果",
          "doc_count": 1,
          "average_price": {
            "value": 5499
          }
        },
        {
          "key": "华为",
          "doc_count": 1,
          "average_price": {
            "value": 3788
          }
        },
        {
          "key": "小米",
          "doc_count": 4,
          "average_price": {
            "value": 2461.5
          }
        },
        {
          "key": "NIKE",
          "doc_count": 2,
          "average_price": {
            "value": 434
          }
        },
        {
          "key": "海澜之家",
          "doc_count": 3,
          "average_price": {
            "value": 88
          }
        }
      ]
    }
  }
}

参考 https://mp.weixin.qq.com/s/cohWZy_eUOUqbmUxhXzzNA

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章