热门标签 | 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 权威指南

推荐阅读
  • 本文节选自《NLTK基础教程——用NLTK和Python库构建机器学习应用》一书的第1章第1.2节,作者Nitin Hardeniya。本文将带领读者快速了解Python的基础知识,为后续的机器学习应用打下坚实的基础。 ... [详细]
  • 基于iSCSI的SQL Server 2012群集测试(一)SQL群集安装
    一、测试需求介绍与准备公司计划服务器迁移过程计划同时上线SQLServer2012,引入SQLServer2012群集提高高可用性,需要对SQLServ ... [详细]
  • 在尝试对 QQmlPropertyMap 类进行测试驱动开发时,发现其派生类中无法正常调用槽函数或 Q_INVOKABLE 方法。这可能是由于 QQmlPropertyMap 的内部实现机制导致的,需要进一步研究以找到解决方案。 ... [详细]
  • 提升Android开发效率:Clean Code的最佳实践与应用
    在Android开发中,提高代码质量和开发效率是至关重要的。本文介绍了如何通过Clean Code的最佳实践来优化Android应用的开发流程。以SQLite数据库操作为例,详细探讨了如何编写高效、可维护的SQL查询语句,并将其结果封装为Java对象。通过遵循这些最佳实践,开发者可以显著提升代码的可读性和可维护性,从而加快开发速度并减少错误。 ... [详细]
  • REST与RPC:选择哪种API架构风格?
    在探讨REST与RPC这两种API架构风格的选择时,本文首先介绍了RPC(远程过程调用)的概念。RPC允许客户端通过网络调用远程服务器上的函数或方法,从而实现分布式系统的功能调用。相比之下,REST(Representational State Transfer)则基于资源的交互模型,通过HTTP协议进行数据传输和操作。本文将详细分析两种架构风格的特点、适用场景及其优缺点,帮助开发者根据具体需求做出合适的选择。 ... [详细]
  • 本文介绍了如何在 Windows 系统上利用 Docker 构建一个包含 NGINX、PHP、MySQL、Redis 和 Elasticsearch 的集成开发环境。通过详细的步骤说明,帮助开发者快速搭建和配置这一复杂的技术栈,提升开发效率和环境一致性。 ... [详细]
  • Linux CentOS 7 安装PostgreSQL 9.5.17 (源码编译)
    近日需要将PostgreSQL数据库从Windows中迁移到Linux中,LinuxCentOS7安装PostgreSQL9.5.17安装过程特此记录。安装环境&#x ... [详细]
  • async/await 是现代 JavaScript 中非常强大的异步编程工具,可以极大地简化异步代码的编写。本文将详细介绍 async 和 await 的用法及其背后的原理。 ... [详细]
  • 在多线程并发环境中,普通变量的操作往往是线程不安全的。本文通过一个简单的例子,展示了如何使用 AtomicInteger 类及其核心的 CAS 无锁算法来保证线程安全。 ... [详细]
  • 原文网址:https:www.cnblogs.comysoceanp7476379.html目录1、AOP什么?2、需求3、解决办法1:使用静态代理4 ... [详细]
  • 解决Bootstrap DataTable Ajax请求重复问题
    在最近的一个项目中,我们使用了JQuery DataTable进行数据展示,虽然使用起来非常方便,但在测试过程中发现了一个问题:当查询条件改变时,有时查询结果的数据不正确。通过FireBug调试发现,点击搜索按钮时,会发送两次Ajax请求,一次是原条件的请求,一次是新条件的请求。 ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • 在Delphi7下要制作系统托盘,只能制作一个比较简单的系统托盘,因为ShellAPI文件定义的TNotifyIconData结构体是比较早的版本。定义如下:1234 ... [详细]
  • V8不仅是一款著名的八缸发动机,广泛应用于道奇Charger、宾利Continental GT和BossHoss摩托车中。自2008年以来,作为Chromium项目的一部分,V8 JavaScript引擎在性能优化和技术创新方面取得了显著进展。该引擎通过先进的编译技术和高效的垃圾回收机制,显著提升了JavaScript的执行效率,为现代Web应用提供了强大的支持。持续的优化和创新使得V8在处理复杂计算和大规模数据时表现更加出色,成为众多开发者和企业的首选。 ... [详细]
  • 2021年Java开发实战:当前时间戳转换方法详解与实用网址推荐
    在当前的就业市场中,金九银十过后,金三银四也即将到来。本文将分享一些实用的面试技巧和题目,特别是针对正在寻找新工作机会的Java开发者。作者在准备字节跳动的面试过程中积累了丰富的经验,并成功获得了Offer。文中详细介绍了如何将当前时间戳进行转换的方法,并推荐了一些实用的在线资源,帮助读者更好地应对技术面试。 ... [详细]
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社区 版权所有