热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

elasticsearch初体验

笔者所有文章第一时间发布于:hhbbz的个人博客 简介 Elasticsearch 是一款稳定高效的分布式搜索和分析引擎,它的底层基于 Lucene,并提供了友好的 RESTful API 来对数

笔者所有文章第一时间发布于:
hhbbz的个人博客

简介

Elasticsearch 是一款稳定高效的分布式搜索和分析引擎,它的底层基于 Lucene,并提供了友好的 RESTful API 来对数据进行操作,还有比较重要的一点是, Elasticsearch 开箱即可用,上手也比较容易。
目前 Elasticsearch 在搭建企业级搜索(如日志搜索、商品搜索等)平台中很广泛,官网也提供了不少案例,比如:

* GitHub 使用 Elasticsearch 检索超过 800 万的代码库 * eBay 使用 Elasticsearch 搜索海量的商品数据 * Netflix 使用 Elasticsearch 来实现高效的消息传递系统

本文主要介绍 Elasticsearch 的基本概念及入门使用。

安装

在安装 Elasticsearch 之前,请确保你的计算机已经安装了 Java。目前 Elasticsearch 的最新版是 5.2,需要安装 Java 8,如果你用的是老版本的 Elasticsearch,如 2.x 版,可用 Java 7,但还是推荐使用 Java 8。

可以使用如下的命令检查 Java 的版本:

$ java -version

接着,下载最新版本的 Elasticsearch,可使用 wget 下载,如下:

$ wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.2.2.tar.gz

Windows 用户也可以下载 .zip 格式的安装包。

下载完后进行解压:

$ tar -zxvf elasticsearch-5.2.2.tar.gz

运行

首先,Elasticsearch不允许通过root管理员运行,所以我们要新建一个非管理员用户。

  1. useradd yourname :新建账户
  2. passwd yourname :设置密码
  3. su yourname:切换到新建账户

然后,我们进入到刚刚解压出来的目录中:

$ cd elasticsearch-5.2.2

接着,使用如下命令启动 Elasticsearch:

$ bin/elasticsearch -d

此时,如果正常的话,你可以在终端看到类似如下的输出:

[2018-08-19T23:25:09,961][INFO ][o.e.n.Node ] [] initializing ... [2018-08-19T23:25:10,073][INFO ][o.e.e.NodeEnvironment ] [yO11WLM] using [1] data paths, mounts [[/ (/dev/disk0s2)]], net usable_space [141.1gb], net total_space [232.9gb], spins? [unknown], types [hfs] [2018-08-19T23:25:10,074][INFO ][o.e.e.NodeEnvironment ] [yO11WLM] heap size [1.9gb], compressed ordinary object pointers [true] [2018-08-19T23:25:10,095][INFO ][o.e.n.Node ] node name [yO11WLM] derived from node ID [yO11WLMOQDuAOpZbYZYjzw]; set [node.name] to override [2018-08-19T23:25:10,100][INFO ][o.e.n.Node ] version[5.2.2], pid[7607], build[db0d481/2017-02-09T22:05:32.386Z], OS[Mac OS X/10.11.5/x86_64], JVM[Oracle Corporation/Java HotSpot(TM) 64-Bit Server VM/1.8.0_102/25.102-b14] [2018-08-19T23:25:11,363][INFO ][o.e.p.PluginsService ] [yO11WLM] loaded module [aggs-matrix-stats] ...

上面的命令是在前台运行的,如果想在后台以守护进程模式运行,可以加 -d 参数。
Elasticsearch 启动后,也启动了两个端口 9200 和 9300:

9200 端口:HTTP RESTful 接口的通讯端口
9300 端口:TCP 通讯端口,用于集群间节点通信和与 Java 客户端通信的端口

现在,让我们做一些测试。在浏览器访问链接 http://localhost:9200/ ,或使用 curl 命令:

$ curl 'http://localhost:9200/?pretty'

我们可以看到类似如下的输出:

{ "name" : "yO11WLM", "cluster_name" : "elasticsearch", "cluster_uuid" : "yC8BGwzlSnu_zGbKL918Xg", "version" : { "number" : "5.2.1", "build_hash" : "db0d481", "build_date" : "2017-02-09T22:05:32.386Z", "build_snapshot" : false, "lucene_version" : "6.4.1" }, "tagline" : "You Know, for Search" } 概念

在进一步使用 Elasticsearch 之前,让我们先了解几个关键概念。

在逻辑层面:

  • Index (索引):这里的 Index 是名词,一个 Index 就像是传统关系数据库的 Database,它是 Elasticsearch 用来存储数据的逻辑区域
  • Document (文档):Elasticsearch 使用 JSON 文档来表示一个对象,就像是关系数据库中一个 Table 中的一行数据
  • Type (类型):文档归属于一种 Type,就像是关系数据库中的一个 Table。(目前官方不推荐使用)
  • Field (字段):每个文档包含多个字段,类似关系数据库中一个 Table 的列

我们用一个表格来做类比,如下:

Elasticsearch MySQL
Index Database
Type Table
Document Row
Field Column

在物理层面:

  • Node (节点):node 是一个运行着的 Elasticsearch 实例,一个 node 就是一个单独的 server
  • Cluster (集群):cluster 是多个 node 的集合
  • Shard (分片):数据分片,一个 index 可能会存在于多个 shard
使用

接下来,我们看看如何建立索引、创建文档等,就好比在 MySQL 中进行诸如创建数据库,插入数据等操作。

添加文档

下面,我们将创建一个存储电影信息的 Document:

  • Index 的名称为 movie
  • Type 为 adventure
  • Document 有两个字段:name 和 actors

我们使用 Elasticsearch 提供的 RESTful API 来执行上述操作,如图所示:

elasticsearch初体验
1.png
  • 用 url 表示一个资源,比如 /movie/adventure/1 就表示一个 index 为 movie,type 为 adventure,id 为 1 的 document
  • 用 http 方法操作资源,如使用 GET 获取资源,使用 POST、PUT 新增或更新资源,使用 DELETE 删除资源等

我们可以使用 curl 命令来执行上述操作:

$ curl -i -X PUT "localhost:9200/movie/adventure/1" -d '{"name": "Life of Pi", "actors": ["Suraj", "Irrfan"]}'

不过,本文推荐使用 httpie,类似 curl,但比 curl 更好用,将上面的命令换成 httpie,如下:

$ http put :9200/movie/adventure/1 name="Life of Pi" actors:='["Suraj", "Irrfan"]'

上面的命令结果如下:

HTTP/1.1 201 Created Location: /movie/adventure/1 content-encoding: gzip content-type: application/json; charset=UTF-8 transfer-encoding: chunked { "_id": "1", "_index": "movie", "_shards": { "failed": 0, "successful": 1, "total": 2 }, "_type": "adventure", "_version": 1, "created": true, "result": "created" }

可以看到,我们已经成功创建了一个 _index 为 movie,_type 为 adventure,_id 为 1 的文档。

我们通过 GET 请求来查看这个文档的信息:

$ http :9200/movie/adventure/1

结果如下:

HTTP/1.1 200 OK content-encoding: gzip content-type: application/json; charset=UTF-8 transfer-encoding: chunked { "_id": "1", "_index": "movie", "_source": { "actors": [ "Suraj", "Irrfan" ], "name": "Life of Pi" }, "_type": "adventure", "_version": 1, "found": true }

可以看到,原始的文档数据存在了 _source 字段中。

如果我们的数据没有 id,也可以让 Elasticsearch 自动为我们生成,此时要使用 POST 请求,形式如下:

POST /movie/adventure/ { "name": "Life of Pi" }

更新整个文档

当我们使用 PUT 方法指明文档的 _index, _type_id时,如果 _id 已存在,则新文档会替换旧文档,此时文档的 _version 会增加 1,并且 _created 字段为 false。比如:

$ http put :9200/movie/adventure/1 name="Life of Pi"

结果如下:

HTTP/1.1 200 OK content-encoding: gzip content-type: application/json; charset=UTF-8 transfer-encoding: chunked { "_id": "1", "_index": "movie", "_shards": { "failed": 0, "successful": 1, "total": 2 }, "_type": "adventure", "_version": 2, "created": false, "result": "updated" }

使用 GET 请求查看新文档的数据:

$ http :9200/movie/adventure/1

结果如下:

HTTP/1.1 200 OK content-encoding: gzip content-type: application/json; charset=UTF-8 transfer-encoding: chunked { "_id": "1", "_index": "movie", "_source": { "name": "Life of Pi" }, "_type": "adventure", "_version": 2, "found": true }

可以看到,actors 这个字段已经不存在了,文档的 _version 变成了 2。
因此,为了避免在误操作的情况下,原文档被替换,我们可以使用 _create 这个 API,表示只在文档不存在的情况下才创建新文档(返回 201 Created),如果文档存在则不做任何操作(返回 409 Conflict),命令如下:

$ http put :9200/movie/adventure/1/_create name="Life of Pi"

由于文档 id 存在,会返回 409 Conflict。

局部更新

在有些情况下,我们只想更新文档的局部,而不是整个文档,这时我们可以使用 _update 这个 API。

现在,待更新的文档信息如下:

{ "_id": "1", "_index": "movie", "_source": { "name": "Life of Pi" }, "_type": "adventure", "_version": 2, "found": true }

最简单的 update 请求接受一个局部文档参数 doc,它会合并到现有文档中:将对象合并在一起,存在的标量字段被覆盖,新字段被添加。

形式如下:

POST /movie/adventure/1/_update { "doc": { "name": "life of pi" } }

由于有嵌套字段,我们可以这样使用 http(这里需要注意使用 POST 方法):

$ echo '{"doc": {"actors": ["Suraj", "Irrfan"]}}' | http post :9200/movie/adventure/1/_update

上面的命令中,我们添加了一个新的字段:actors,结果如下:

HTTP/1.1 200 OK content-encoding: gzip content-type: application/json; charset=UTF-8 transfer-encoding: chunked { "_id": "1", "_index": "movie", "_shards": { "failed": 0, "successful": 1, "total": 2 }, "_type": "adventure", "_version": 3, "result": "updated" }

可以看到,_version 增加了 1,result 的结果是 updated。

检索文档

检索某个文档

要检索某个文档很简单,我们只需使用 GET 请求并指出文档的 index, type, id 就可以了,比如:

$ http :9200/movie/adventure/1/

响应内容会包含文档的元信息,文档的原始数据存在 _source 字段中。

我们也可以直接检索出文档的 _source 字段,如下:

$ http :9200/movie/adventure/1/_source

检索所有文档

我们可以使用 _search 这个 API 检索出所有的文档,命令如下:

$ http :9200/movie/adventure/_search

返回结果如下:

{ "_shards": { "failed": 0, "successful": 5, "total": 5 }, "hits": { "hits": [ { "_id": "1", "_index": "movie", "_score": 1.0, "_source": { "actors": [ "Suraj", "Irrfan" ], "name": "Life of Pi" }, "_type": "adventure" } ], "max_score": 1.0, "total": 1 }, "timed_out": false, "took": 299 }

可以看到,hits 这个 object 包含了 hits 数组,total 等字段,其中,hits 数组包含了所有的文档,这里只有一个文档,total 表明了文档的数量,默认情况下会返回前 10 个结果。我们也可以设定 From/Size 参数来获取某一范围的文档,可参考这里,比如:

$ http :9200/movie/adventure/_search?from=1&size=5

当不指定 from 和 size 时,会使用默认值,其中 from 的默认值是 0,size 的默认值是 10。

检索某些字段

有时候,我们只需检索文档的个别字段,这时可以使用 _source 参数,多个字段可以使用逗号分隔,如下所示:

$ http :9200/movie/adventure/1?_source=name $ http :9200/movie/adventure/1?_source=name,actors

query string 搜索

query string 搜索以 q=field:value 的形式进行查询,比如查询 name 字段含有 life 的电影:

$ http :9200/movie/adventure/_search?q=name:life

DSL 搜索

上面的 query string 搜索比较轻量级,只适用于简单的场合。Elasticsearch 提供了更为强大的 DSL(Domain Specific Language)查询语言,适用于复杂的搜索场景,比如全文搜索。我们可以将上面的 query string 搜索转换为 DSL 搜索,如下:

GET /movie/adventure/_search { "query" : { "match" : { "name" : "life" } } }

如果使用 httpie,可以这样:

$ echo '{"query": {"match": {"name": "life"}}}' | http get :9200/movie/adventure/_search

如果使用 curl,可以这样:

$ curl -X GET "127.0.0.1:9200/movie/adventure/_search" -d '{"query": {"match": {"name": "life"}}}'

文档是否存在

使用 HEAD 方法查看文档是否存在:

$ http head :9200/movie/adventure/1

如果文档存在则返回 200,否则返回 404。

删除文档

$ http delete :9200/movie/adventure/1 小结

  • Elasticsearch 通过简单的 RESTful API 来隐藏 Lucene 的复杂性,从而让全文搜索变得简单
  • 在创建文档时,我们可以用 POST 方法指定将文档添加到某个 _index/_type 下,来让 Elasticsearch自动生成唯一的 _id;而用 PUT 方法指定将文档的 _index/_type/_id
参考资料
  • Elasticsearch Reference
  • Elasticsearch 权威指南

推荐阅读
  • 基址获取与驱动开发:内核中提取ntoskrnl模块的基地址方法解析
    基址获取与驱动开发:内核中提取ntoskrnl模块的基地址方法解析 ... [详细]
  • 在软件开发过程中,经常需要将多个项目或模块进行集成和调试,尤其是当项目依赖于第三方开源库(如Cordova、CocoaPods)时。本文介绍了如何在Xcode中高效地进行多项目联合调试,分享了一些实用的技巧和最佳实践,帮助开发者解决常见的调试难题,提高开发效率。 ... [详细]
  • 在尝试对 QQmlPropertyMap 类进行测试驱动开发时,发现其派生类中无法正常调用槽函数或 Q_INVOKABLE 方法。这可能是由于 QQmlPropertyMap 的内部实现机制导致的,需要进一步研究以找到解决方案。 ... [详细]
  • 在对WordPress Duplicator插件0.4.4版本的安全评估中,发现其存在跨站脚本(XSS)攻击漏洞。此漏洞可能被利用进行恶意操作,建议用户及时更新至最新版本以确保系统安全。测试方法仅限于安全研究和教学目的,使用时需自行承担风险。漏洞编号:HTB23162。 ... [详细]
  • 优化后的标题:深入探讨网关安全:将微服务升级为OAuth2资源服务器的最佳实践
    本文深入探讨了如何将微服务升级为OAuth2资源服务器,以订单服务为例,详细介绍了在POM文件中添加 `spring-cloud-starter-oauth2` 依赖,并配置Spring Security以实现对微服务的保护。通过这一过程,不仅增强了系统的安全性,还提高了资源访问的可控性和灵活性。文章还讨论了最佳实践,包括如何配置OAuth2客户端和资源服务器,以及如何处理常见的安全问题和错误。 ... [详细]
  • 在PHP中实现腾讯云接口签名,以完成人脸核身功能的对接与签名配置时,需要注意将文档中的POST请求改为GET请求。具体步骤包括:使用你的`secretKey`生成签名字符串`$srcStr`,格式为`GET faceid.tencentcloudapi.com?`,确保参数正确拼接,避免因请求方法错误导致的签名问题。此外,还需关注API的其他参数要求,确保请求的完整性和安全性。 ... [详细]
  • REST API 时代落幕,GraphQL 持续引领未来
    尽管REST API已广泛使用多年,但在深入了解GraphQL及其解决的核心问题后,我深感其将引领未来的API设计趋势。GraphQL不仅提高了数据查询的效率,还增强了灵活性和性能,有望成为API开发的新标准。 ... [详细]
  • 本文深入探讨了ASP.NET Web API与RESTful架构的设计与实现。ASP.NET Web API 是一个强大的框架,能够简化HTTP服务的开发,使其能够广泛支持各种客户端设备。通过详细分析其核心原理和最佳实践,本文为开发者提供了构建高效、可扩展且易于维护的Web服务的指导。此外,还讨论了如何利用RESTful原则优化API设计,确保系统的灵活性和互操作性。 ... [详细]
  • 如何将TS文件转换为M3U8直播流:HLS与M3U8格式详解
    在视频传输领域,MP4虽然常见,但在直播场景中直接使用MP4格式存在诸多问题。例如,MP4文件的头部信息(如ftyp、moov)较大,导致初始加载时间较长,影响用户体验。相比之下,HLS(HTTP Live Streaming)协议及其M3U8格式更具优势。HLS通过将视频切分成多个小片段,并生成一个M3U8播放列表文件,实现低延迟和高稳定性。本文详细介绍了如何将TS文件转换为M3U8直播流,包括技术原理和具体操作步骤,帮助读者更好地理解和应用这一技术。 ... [详细]
  • Maven Web项目创建时JSP文件常见错误及解决方案
    Maven Web项目创建时JSP文件常见错误及解决方案 ... [详细]
  • Java Socket 关键参数详解与优化建议
    Java Socket 的 API 虽然被广泛使用,但其关键参数的用途却鲜为人知。本文详细解析了 Java Socket 中的重要参数,如 backlog 参数,它用于控制服务器等待连接请求的队列长度。此外,还探讨了其他参数如 SO_TIMEOUT、SO_REUSEADDR 等的配置方法及其对性能的影响,并提供了优化建议,帮助开发者提升网络通信的稳定性和效率。 ... [详细]
  • 卓盟科技:动态资源加载技术的兼容性优化与升级 | Android 开发者案例分享
    随着游戏内容日益复杂,资源加载过程已不仅仅是简单的进度显示,而是连接玩家与开发者的桥梁。玩家对快速加载的需求越来越高,这意味着开发者需要不断优化和提升动态资源加载技术的兼容性和性能。卓盟科技通过一系列的技术创新,不仅提高了加载速度,还确保了不同设备和系统的兼容性,为用户提供更加流畅的游戏体验。 ... [详细]
  • 在处理 XML 数据时,如果需要解析 `` 标签的内容,可以采用 Pull 解析方法。Pull 解析是一种高效的 XML 解析方式,适用于流式数据处理。具体实现中,可以通过 Java 的 `XmlPullParser` 或其他类似的库来逐步读取和解析 XML 文档中的 `` 元素。这样不仅能够提高解析效率,还能减少内存占用。本文将详细介绍如何使用 Pull 解析方法来提取 `` 标签的内容,并提供一个示例代码,帮助开发者快速解决问题。 ... [详细]
  • 该问题可能由守护进程配置不当引起,例如未识别的JVM选项或内存分配不足。建议检查并调整JVM参数,确保为对象堆预留足够的内存空间(至少1572864KB)。此外,还可以优化应用程序的内存使用,减少不必要的内存消耗。 ... [详细]
  • 在数据库事务处理中,InnoDB 存储引擎提供了多种隔离级别,其中 READ COMMITTED 和 REPEATABLE READ 是两个常用的选项。本文详细对比了这两种隔离级别的特点和差异,不仅从理论角度分析了它们对“脏读”和“幻读”的处理方式,还结合实际应用场景探讨了它们在并发控制和性能表现上的不同。特别关注了行锁机制在不同隔离级别下的行为,为开发者选择合适的隔离级别提供了参考。 ... [详细]
author-avatar
手机用户2502857731
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有