Elasticsearch实战

978-7-115-44915-3
作者: [美] 拉杜•乔戈(Radu Gheorghe) 马修•李•欣曼(Matthew Lee Hinman)罗伊•罗素(Roy Russo)
译者: 黄申
编辑: 杨海玲

图书目录:

详情

本书主要展示如何使用Elasticsearch构建可扩展的搜索应用程序。书中覆盖了Elasticsearch的主要特性,从使用不同的分析器和查询类型进行相关性调优,到使用聚集功能进行实时性分析,还有地理空间搜索和文档过滤等更多吸引人的特性。 全书共分两个部分,第一部分解释了核心特性,第二部分介绍每个特性工作的更多细节及其对性能和可扩展性的影响,以便对核心功能进行产品化。此外,本书还有6个附录。

图书摘要

版权信息

书名:Elasticsearch实战

ISBN:978-7-115-44915-3

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。

著    [美]拉杜•乔戈(Radu Gheorghe)

     马修•李•欣曼(Matthew Lee Hinman)

     罗伊•罗素(Roy Russo)

译    黄 申

责任编辑 杨海玲

人民邮电出版社出版发行  北京市丰台区成寿寺路11号

邮编 100164  电子邮件 315@ptpress.com.cn

网址 http://www.ptpress.com.cn

读者服务热线:(010)81055410

反盗版热线:(010)81055315


Original English language edition, entitled Elasticsearch in Action by Willliam Kennedy, Brian Ketelsen, and Erik St. Martin published by Manning Publications Co., 209 Bruce Park Avenue, Greenwich, CT 06830. Copyright ©2016 by Manning Publications Co.

Simplified Chinese-language edition copyright ©2018 by Posts & Telecom Press. All rights reserved.

本书中文简体字版由Manning Publications Co.授权人民邮电出版社独家出版。未经出版者书面许可,不得以任何方式复制或抄袭本书内容。

版权所有,侵权必究。


本书主要展示如何使用Elasticsearch构建可扩展的搜索应用程序。书中覆盖了Elasticsearch的主要特性,从使用不同的分析器和查询类型进行相关性调优,到使用聚集功能进行实时性分析,还有地理空间搜索和文档过滤等更多吸引人的特性。

全书共分两个部分,第一部分解释了核心特性,内容主要涉及Elasticsearch的介绍,数据的索引、更新和删除,数据的搜索,数据的分析,使用相关性进行搜索,使用聚集来探索数据,文档间的关系等;第二部分介绍每个特性工作的更多细节及其对性能和可扩展性的影响,以便对核心功能进行产品化,内容主要涉及水平扩展和性能提升等。此外,本书还有6个附录(网上下载),提供了读者应该知道的特性,展示了关于地理空间搜索和聚集,如何管理Elasticsearch插件,学习在搜索结果中如何高亮查询单词,在生产环境中用来协助管理Elasticsearch的第三方的监控工具有哪些,如何使用Percolator过滤为多个查询匹配少量文档,如何使用不同的建议器来实现自动完成的功能。

本书适合所有对Elasticsearch感兴趣的技术人员阅读。


很早就看到这本书的英文版了,非常高兴现在能看到有中文版上市,也很荣幸能为本书作序。

Manning出版社的“in Action”系列的书质量基本上都不会差。我记得最早学习Lucene的时候,买过或者看过很多介绍Lucene或者搜索引擎相关的书籍,其中有些书要么晦涩难懂,底层算法介绍和应用有点儿脱节,看完之后还是一头雾水,要么仅仅停留在实战,鲜有提及背后的原理知识,全书咀嚼价值不大,唯独Lucene in Action这本书看完之后让我有种透彻的感觉。

世界是如此奇妙,多年后,我在Elastic有幸能够当面见到Lucene in Action这本书的作者Michael McCandless本人,并对他表示感谢。无独有偶,Elasticsearch in Action这本书的作者之一Lee Hinman目前也在Elastic公司,Lee同时也是Elasticsearch的核心开发工程师。阅读这本书读者会发现,这本书不仅包括很多实际的调用例子,还对各项功能背后的原理进行了非常详尽的阐述,并辅以图表流程让读者加深理解,实在是目前市面上少有的能够将Elasticsearch介绍得如此透彻的书,而Lee听说本书将有中文版也很高兴。

本书由浅入深,前面3章介绍Elasticsearch的基本用法,第4、5和6章介绍全文检索以及如何进行高级的评分和自定义排序,第7章涵盖各种聚合的使用,其后几章介绍数据结构设计、集群、运维和性能优化等各种知识和技巧,都是非常全面有用的知识,附录的内容干货也很多,地理位置搜索、插件介绍、高亮、自动补全、拼写检查,基本上涉及了围绕搜索相关的方方面面。相信对照本书,读者可以很快搭建一个功能丰富的搜索站点出来。

我们社区曾翻译过一本Elasticsearch权威指南,深知翻译工作的不容易,背后少不了需要进行大量的斟酌讨论和反复修改。有了译者和编辑的付出,才有了这本书,大家学习Elasticsearch又多了一本很好的参考书。

Elasticsearch及Elastic的其他产品最近几年发展很快,简单易用、功能丰富还不失优越的性能,在全球可谓是广受欢迎,用户场景也是非常丰富,2015年产品的累积下载次数就突破了一亿,对于一个开源产品来说实在是不简单。Elasticsearch的未来值得期待。

祝大家阅读愉快!

Medcl

Elastic布道师


谈到为什么要翻译这本书,还是一段机缘巧合。那是2015年的下半年,当时我正在撰写自己的原创书籍《大数据架构商业之路:从业务需求到技术方案》。由于在之前的实际项目中也经常使用Elasticsearch,所以书中提到了Elasticsearch相关的概念以及如何用其架构基础的搜索引擎。我将初稿送给一位朋友,让他帮我提提建议,而他的一个问题难倒了我:“看过你的稿子,我对其中提到的Elasticsearch特别感兴趣,有没有专门的书对其进行系统性介绍的?”

在那个时候,Elasticsearch在国内刚刚开始流行,我们多是直接参考官网的资料。不过,官网的资料适合有一定经验和基础的开发者,对于普通爱好者而言门槛有点高了。于是,我搜索了市面上Elasticsearch相关的书籍,可惜并未发现特别好的材料。无意之间,我在Amazon.com上发现了即将出版的Elasticsearch in Action,于是到Manning下载了试读版。在阅读之后我不禁暗喜,这本书的内容比较系统全面,难度由浅入深,并且继承了Manning出版社实战系列(in Action)一贯的作风,让读者可以轻松上手,乐在其中。这正是我想推荐给朋友的!可惜,英文版尚未发行,更何谈中文版?不过,我是否能贡献自己的力量,让这本书的中文版尽快面世呢?于是,我抱着试试看的心态,联系了人民邮电出版社的编辑杨海玲老师。很幸运,当时此书还没有译者,于是我很荣幸地成为本书的译者。

不过翻译的过程比我想象的要艰辛。这主要是因为Elasticsearch的功能过于强大。随着阅读和翻译的不断深入,我发现之前只是使用了Elasticsearch中很小的一部分特性。对于新内容,我也碰到一些自己难以理解的地方。于是我主动联系了原书的第一作者Radu,他总是非常仔细地解答我的问题,这使我更有信心,可以确保译文尽可能地贴近原文。在此,我要对Radu的帮助表示衷心的感谢。当然,我也要感谢父母和妻儿的支持,为了此书,我陪伴你们的时间更少了,而你们丝毫没有怨言,让我可以安心地完成这本书的翻译工作。

最后,很高兴此书终于和大家见面了。在翻译此书的大半年中,Elasticsearch在国内外都获得了空前的关注,社区也保持了非常好的活跃度,相信这门技术在将来还有很大的发展空间。希望本书能帮助到每一位热爱Elasticsearch的朋友,为Elasticsearch的发展尽一份绵薄之力。如果读者对本书中的技术细节感兴趣,可以通过如下渠道联系我,很期待和大家的互动和交流。

QQ 36638279

微信 18616692855

邮箱 s_huang790228@hotmail.com

LinkedIn https://cn.linkedin.com/in/shuang790228

扫一扫就能微信联系译者:

译者个人微信

微信公众号


黄申博士,现任LinkedIn(领英)资深数据科学家,毕业于上海交通大学计算机科学与工程专业,师从俞勇教授。微软学者、IBM ExtremeBlue天才计划成员。长期专注于大数据相关的搜索、推荐、广告以及用户精准化领域。曾在微软亚洲研究院、eBay中国、沃尔玛1号店(现京东1号店)和大润发飞牛网担任要职,带团队完成了若干公司级的战略项目。同时在国际上发表20多篇论文,并拥有10多项国际专利。《计算机工程》特邀审稿专家,2016年出版了《大数据架构商业之路》一书,广受好评。因对业界做出卓越贡献,获得美国政府颁发的“美国杰出人才”称号。


我写这本书的目的在于向读者提供开始使用Elasticsearch时所需的信息:它的主要特性有哪些,这些特性在整个引擎中又是怎样运作的,为了给出更好的概览,让我告诉你一个更详细的故事,关于这本书是如何诞生的。

我第一次邂逅Elasticsearch是在2011年,那时我正在开发一个集中化日志的项目。同事Mihai Sandu向我展示了Graylog,这个系统采用Elasticsearch进行日志的搜索,一切的配置都异常简单。两台服务器就可以处理当时所有的日志需求,但是我们预料数据量会在1年左右增长数百倍,而且事实确实如此。基于此,我们有越来越多的复杂分析需求,所以我们很快发现需要对Elasticsearch和它的特性拥有更深入的理解,才能调优和扩展其设置。

当时没有书籍可以指导我们,所以我们只能通过艰难的方式进行学习:反复实验、在邮件列表里多次提出问题和进行回答。幸运的是,我结识了许多友善的人,他们定期都会发帖提供帮助。这是我在Sematext公司工作的原因,在那里我全身心地投入到Elasticsearch中,这也是为什么Manning出版社问我是否对于写一本关于Elasticsearch的书感兴趣。

我当然感兴趣。他们告诫我这是一项艰巨的任务,不过同时告知我Lee Hinman也很感兴趣,于是我们联手了。有了两个作者,大家认为事情变得容易了。尤其是Lee和我都是亲自实践,并且向对方提供了有用的反馈。之前我们几乎没有意识到,相比在前面的章节中展示特性,在后面的章节中将各项特性结合到不同用例的最佳实践中要困难得多。随后,通过审阅者的反馈,我们发现将所有的事情糅合在一起需要更多的工作量,前进的步伐也变得越来越慢。这时Roy Russo加入了这个团队,并帮助进行了最后的推动。

经过2年半夜以继日,加班加点地创作,终于大功告成。这是个很艰难的历程,但是也很充实。如果4年前有这本书在手,我一定爱死它了。希望读者能享受这本书。

 

Radu Gheorghe


本书由异步社区出品,社区(https://www.epubit.com/)为您提供相关资源和后续服务。

本书提供源代码下载,要获得源代码请在异步社区本书页面中点击 ,跳转到下载界面,按提示进行操作即可。注意:为保证购书读者的权益,该操作会给出相关提示,要求输入提取码进行验证。

作者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏。欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量。

当您发现错误时,请登录异步社区,按书名搜索,进入本书页面,点击“提交勘误”,输入勘误信息,点击“提交”按钮即可。本书的作者和编辑会对您提交的勘误进行审核,确认并接受后,您将获赠异步社区的100积分。积分可用于在异步社区兑换优惠券、样书或奖品。

我们的联系邮箱是contact@epubit.com.cn。

如果您对本书有任何疑问或建议,请您发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。

如果您有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们;有意出版图书的作者也可以到异步社区在线提交投稿(直接访问www.epubit.com/selfpublish/ submission即可)。

如果您是学校、培训机构或企业,想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。

如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接发邮件给我们。您的这一举动是对作者权益的保护,也是我们持续为您提供有价值的内容的动力之源。

“异步社区”是人民邮电出版社旗下IT专业图书社区,致力于出版精品IT技术图书和相关学习产品,为作译者提供优质出版服务。异步社区创办于2015年8月,提供大量精品IT技术图书和电子书,以及高品质技术文章和视频课程。更多详情请访问异步社区官网https://www.epubit.com。

“异步图书”是由异步社区编辑团队策划出版的精品IT专业图书的品牌,依托于人民邮电出版社近30年的计算机图书出版积累和专业编辑团队,相关图书在封面上印有异步图书的LOGO。异步图书的出版领域包括软件开发、大数据、AI、测试、前端、网络技术等。

异步社区

微信服务号


正因为很多人提供了无价的支持,才使得这本书的面市成为可能。

我按照时间顺序表达感谢。致我Avira的同事:Mihai Sandu、Mihai Efrim、Martin Ahrens、Matthias Ollig和很多其他人,支持我学习Elasticsearch,而且容忍我并非总是成功的实验。感谢我Sematext的同事Otis Gospodnetić,支持我学习以及进行和社区的互动。感谢Rafał Kuć(又名Master Rafał)提供宝贵的技巧和窍门。最后,要感谢我的家庭为我提供各方面的支持,这里只能蜻蜓点水地提一下:我的父母Nicoelta和Mihai Gheorghe,我的岳父岳母Mădălina和Adrian Radu,提供了美味的佳肴、安静的空间和至关重要的精神支持。我的爱妻Alexandra是个真正的英雄:她设法在撰写自己的作品的同时,仍然照顾好所有的事情,来保障我的写作。还有一点很重要的是:我6岁的儿子Andrei,感谢他的谅解以及和我共度时光的创新方式,就好像他依偎在我身旁撰写他自己的书。

首先,我要向爱妻Delilah表达诚挚的感谢,她鼓励我进行尝试,成为我冒险的伙伴,在著书和生活的许多方面给予了我很大的支持。感谢她在女儿Vera Ovelia诞生期间继续鼓励我。我还要感谢所有为Elasticsearch做出贡献的人们。没有你们,开源软件不会成为可能。我很荣幸能为这样一个广泛应用而且功能强大的软件项目做出贡献。

我要感谢我的女儿Olivia和Isabella、我的儿子Jacob和我的妻子Roberta。你们在我的身后支持我的事业,成为我灵感和动力的源泉。你们通过支持、关爱和理解,将不可能化为可能。


自从2010年问世,Elasticsearch已经逐渐流行起来。它被用于不同的场景,从产品搜索这种传统的搜索引擎使用模式,到实时性的社会媒体、应用日志和其他流式数据的分析。Elasticsearch的强项在于它的分布式模型(使得其可以便捷而又有效地进行水平扩展),还有丰富的分析功能。所有这些都是构建在已有的Apache Lucene搜索引擎包之上。Lucene也在与时俱进,处理同样数量的数据,可以花费更少的CPU计算、内存容量和磁盘空间。

本书覆盖了Elasticsearch的主要特性,从使用不同的分析器和查询类型进行相关性的调优,到使用聚集功能进行实时性分析,还有更多吸引人的特性,如地理空间搜索和文档过滤。

读者将很快发现,Elasticsearch是很容易上手的。读者可以放入文档、搜索它们、建立统计,甚至是在数小时内将数据分发并复制到多台机器上。默认的行为和设置对于程序员而言是非常友好的,使得概念验证的建立非常容易。

从原型到生产系统通常是件很困难的事情,因为会碰到各种功能或性能的限制。这也是为什么我们会解释在引擎盖之下,各个部件是如何工作的。这样就可以调整合适的选项,以获得良好的搜索相关性和集群的读写性能。

具体来讲,我们将讨论哪些特性?来看看本书路线图的一些细节。

本书分为两个部分:“核心功能”和“高级功能”。我们建议按照顺序阅读每一章,原因是某个章节中的功能经常依赖于之前章节表述的概念。如果你喜欢事必躬亲的方式,每一章都包含可以参考的代码清单和代码片段,但是你并不需要用笔记本电脑来学习Elasticsearch的概念和它是如何工作的。

第一部分解释了核心特性——如何建模和索引数据,这样可以根据用例的需求来进行搜索和分析。在此部分的最后,读者将理解Elasticsearch功能的基础元件。

第二部分帮助读者对核心功能进行产品化。为了实现这个目标,读者将学习每个特性工作的更多细节,及其对于性能和可扩展性的影响。

本书的6个附录包含了读者应该知道的特性,但是这些特性和某些用例并不相关。希望“附录”这个词不会让人误认为我们对其阐述是肤浅的。本书余下的部分将深入如下功能运作的细节。

所有代码清单和文本中的源代码都是用等宽字体来区分的。很多代码清单都有注解,强调重要的概念。

本书中所有样例的可运行源代码,以及如何运行它们的指导,都能从https://github.com/dakrone/ elasticsearch-in-action获得。读者也可以从Manning出版社的网站下载源代码。

代码片段和源代码可以在Elasticsearch 1.5版本上运行。它们应该可以在所有1.x分支版本上运行。在写这本书的时候,版本2.0的路线图也变得清晰起来,这一点也已经考虑在内:我们跳过了即将淘汰的特性,如大多数预定义字段的配置选项。还有其他的,如过滤器缓存,在1.x和2.x版本中的行为表现截然不同,我们已在标注中特别指出。

购买本书的权益包括Manning出版社个人网络论坛的免费访问权限,在该论坛中读者可以对书籍进行评价,提出技术问题,并且获得作者和其他用户的帮助。要访问和订阅作者在线论坛,可在浏览器里访问www.manning.com/books/elasticsearch-in-action。这个页面提供了很多信息,包括如何在注册后登录论坛、可以获得何种帮助以及论坛上的行为准则。

Manning出版社对读者的承诺是,提供一个场所,让读者之间、读者和作者之间进行有意义的对话,但并未承诺具体的作者的参与程度,作者对论坛的贡献仍然是保持自愿的原则。

只要本书还在销售中,作者在线论坛、之前讨论的存档就可以通过出版社网站获取。


本书封面的画像名为“来自克罗地亚的男人”。这幅插图选自19世纪中叶Nikola Arsenovic所著克罗地亚传统服装图集的复制品,由克罗地亚独立民族博物馆于2003年出版。通过独立民族博物馆的管理员获得。这家博物馆位于城镇中世纪中心的罗马核心——公元304年左右Diocletian皇帝隐退的宫殿。这本书包含了克罗地亚不同地区人物的精美插图,描绘了他们的服饰和日常生活。

在过去的200年里,人类着装风范和生活方式都发生了改变。而今当时极为丰富的地区多样性也已逐渐消失。现在很难区分各大洲的居民,更不用说相隔只有数千米的村庄或城镇。也许我们已经用文化的差异换取了不同的个人生活,肯定是一种更为不同、快节奏的科技化生活。

Manning出版社通过图书封面反映两个世纪前丰富多样的地域生活,以此来庆祝计算机业的创造性和原创性。如此古老的书籍和收藏的插画,仿佛把我们带回到过去的日子。


在这部分中,我们将讨论按照功能来看Elasticsearch能做些什么。第1章将从更为宽泛的概念开始,探索Elasticsearch通常是如何用作搜索引擎,以及如何高效地建立模型、建立索引、搜索和分析数据。读完第一部分,读者将对Elasticsearch能提供什么功能、如何使用它解决搜索和实时分析问题有深入的理解。


本章主要内容

如今,我们无处不在地使用“搜索”。这是件好事,因为搜索能帮你从容不迫地完成手头上的工作。无论是在线购物,还是访问博客,你都不会心甘情愿地将整个站点翻个底朝天,而是更希望有个搜索框适时地出现,帮助你发现真心想要的。也许只有我是这样的人,当我(Radu)在清晨醒来的时候,多么希望进入厨房后,能有个搜索框让人可以直接输入“碗”这个词,然后最心爱的碗就出现在面前。

我们也很期待这些搜索框变得更智能。没有必要输入“碗”这个词所需的全部字母(要知道,在英文里bowl要输入4个字母);希望搜索框能有自动提示的功能,而且提示的内容要合理,不能胡乱提示。搜索返回的内容也要智能些,最相关的结果要排在前面:简单来说就是尽可能猜中用户想要什么。举个例子,在线购物时,我搜索了“笔记本电脑”,发现排在前面的都是笔记本的配件,往下翻了很多才看到真正的电脑,那看完这页后我一定会去其他家买了。我们需要看到最相关的结果和提示,一方面是因为人们生活节奏很快,被许多良好的搜索体验宠坏后不愿意再浪费时间;另一个方面,有越来越多的东西可供选择。再举个例子,一位朋友让我帮她挑台新的笔记本电脑。如果查询“为我的朋友购买一台最棒的笔记本电脑”,那么一家在线商店即使销售成千上万款别致的电脑,它也不太可能给出有效的答案。良好的关键字查询往往还不够,你还需要从搜索结果中得到一些统计信息,并利用其定位用户的兴趣。我会选择屏幕的尺寸、价格区间等来逐步缩小选择的范围,直到将目标锁定到5台左右的电脑。

最后,还需要考虑性能问题,因为没有人愿意等待。我曾经在一些网站上有过糟糕的经历,搜索过后数分钟结果才展现出来。注意,单位是分钟!一次搜索竟然花了这么久。

如果你想让自己的数据能被搜索,需要处理如下事项:返回相关的搜索结果,返回统计信息,而且要非常快速地完成。这就是Elasticsearch这种搜索引擎存在的意义,因为它们生来就是迎接这些挑战的。它可以在关系型数据库上搭建搜索引擎,建立索引并加速SQL查询的执行。或许,也可以从NoSQL数据存储上建立索引,然后支持搜索功能。可以通过Elasticsearch做到这些,此外由于Elasticsearch里的数据是通过文档形式表示的,它和MongoDB这种面向文档的存储搭配起来也很美妙。Elasticsearch这样的现代搜索引擎还能完好地存储数据,甚至可以将其直接作为带搜索功能的NoSQL数据存储来使用。

Elasticsearch是构建在Apache Lucene之上的开源分布式搜索引擎。Lucene是开源的搜索引擎包,允许你通过自己的Java应用程序实现搜索功能。Elasticsearch充分利用Lucene,并对其进行了扩展,使存储、索引、搜索都变得更快、更容易,而最重要的是,正如名字中的“elastic”所示,一切都是灵活、有弹性的。而且,应用代码也不是必须用Java书写才可以和Elasticsearch兼容,你完全可以通过JSON格式的HTTP请求来进行索引、搜索和管理Elasticsearch集群。

本章将阐述搜索和数据的特性,你将在本书中学习如何使用它们。首先,让我们来近距离体验一下搜索引擎通常面临的挑战,以及Elasticsearch应对这些挑战的解决方案吧。

为了更好地理解Elasticsearch是如何工作的,让我们先看一个示例。假设你正在搭建一个博客网站,并且希望用户可以在全站搜索特定的帖子。要完成的第一项任务就是实现基于关键词的搜索。例如,一位用户查询“选举”,系统需要返回所有包含这个关键词的帖子。

搜索引擎将完成这些工作,但是对于一个健壮的搜索功能而言,你需要更多特性:引擎可以快速地返回查询结果,而且这些结果都是相关的。当用户并不清楚具体要用哪些词来查找时,搜索还能提供辅助的功能,用于实现更佳的用户体验。这些辅助的功能具体包括识别错误的输入,给出自动提示,并对结果进行分类。

提示

 

本章的大部分内容将有助于你了解Elasticsearch的特性。如果你是个急性子,迫不及待想实战一把,并准备安装它了,可以直接跳到1.5节。你会发现原来安装如此之简单。当然,也可以随时回到这里,看看整体的概述。

如果网站上有很多帖子,在其中查找“选举”这个词会非常耗时。你当然不希望用户一直等着。Elasticsearch恰好能帮上忙,因为它是采用Lucene作为底层的。Lucene是个高性能的搜索引擎包,默认情况下会将所有的数据全部进行索引。

这里所说的索引是一种数据结构,它依据你的数据建造,最终会让搜索变得非常迅速。在大多数据库中,可以使用几种不同的方式为字段添加索引。而Lucene使用的是倒排索引,这意味着它将创建一个数据结构,并在其中保存记录每个单词出现在哪些数据中的清单。例如,如果你想按照标签来搜索博客文章,倒排索引看上去就会如表1-1所示。

表1-1 博客标签的倒排索引

原始数据

索引数据(倒排索引)

博客文章ID

标签

标签

博客文章ID

1

elections

elections

13

2

peace

peace

234

3

electionspeace

4

peace

如果搜索含有elections(选举)标签的帖子,那么相对查找原始数据而言,查找倒排索引后的数据会更快捷。因为只需要查看标签是elections这一栏,然后获得相应所有的文章ID(这里是1和3)。在搜索引擎的应用场景下,这种速度的提升是非常必要的。在现实世界中,你基本不会只查询1个关键词。例如,如果搜“Elasticsearch in Action”,3个词就意味着查询速度提升了3倍。现在看来这有点儿晦涩难懂,不过没关系,在第3章讨论建立索引和第4章讨论搜索时,我们将解释更多的细节。

即使考虑到相关性,倒排索引对于搜索引擎而言也是一个适合的方案。举个例子,当查找“peace”(和平)这样的单词时,你不仅可以看到哪些文档是匹配的,还能免费获得这些文档的总数。这一点很关键,原因是一个词如果出现在很多文档中,那么它很可能和每个文档都不太相关了。就说搜索的“Elasticsearch in Action”吧,有个文档包括“in”这个单词(当然还有上百万个文档也包括“in”)。你会意识到“in”是个常见词,即使这个文档因为包含“in”而匹配成功,也不代表它和查询有多相关。对比之下,如果这个文档包含“Elasticsearch”(可能还有数百个文档也包含“Elasticsearch”),你就知道离相关文档不远了。其实,知道离答案更进一步的并不是“你”,而是Elasticsearch替你完成了。在第6章中,读者将会学到如何通过调优数据和搜索来提升相关性。

同时,为了提升搜索的性能和相关性,还需要更多的磁盘空间来存储索引。增加新的博客帖子会越来越慢,因为每次添加数据就要更新索引。对此,调优可以让Elasticsearch无论在索引还是搜索时都变得更快。我们将在第10章详细讨论这些细节。

接下来有一个难题:如何将真正描述选举的帖子排序在前呢?有了Elasticsearch,就可以使用几个算法来计算相关性的得分(relevancy score),然后根据分数来将结果逐个排序。

对于每个符合查询条件的文档,它的相关性得分标示该文档和查询条件的相关程度。例如,一条博客帖子多次出现了“elections”,频率超过了其他的帖子,那么该文章讨论选举相关的话题的可能性就更大。这里我们看下DuckDuckGo的示例,如图1-1所示。

图1-1 如果文档出现更多的查询关键词(加粗的那些),它就会拥有靠前的排名

默认情况下,计算文档相关性得分的算法是TF-IDF(term frequency-inverse document frequency,词频-逆文档频率)。我们将在讨论搜索和相关性的第4章和第6章中,进一步讨论得分和TF-IDF的更多细节。这里先讲一下基本概念——TF-IDF,下面是会影响相关性得分的两个因素。

例如,当在自行车爱好者的博客上搜索“自行车竞赛”的时候,因为“自行车”在所有文档中出现的频率要高于“竞赛”,所以对最后得分贡献较小。同时,一篇文章中二者出现次数越多,这篇文章的得分也会越高。

除了选择算法,Elasticsearch还提供了很多其他内置的功能来计算相关性得分,以满足定制需求。例如,你可以“提升”特定字段的得分:从相关性的角度考虑,帖子的标题比文章主体更为重要。这样标题上相匹配的文档会比仅仅在主体中匹配上的文档获得更高的分数。你也可以让精确匹配比部分匹配获得更高的分数,甚至通过脚本添加定制条件来改变得分的计算。例如,如果帖子允许用户点赞,可以根据点赞数来提升得分,或者让新的帖子获得更高得分,排在较旧的帖子之前。

现在不用担心这些特性的具体机制。第6章中会讨论更多相关性的细节。当下,让我们重点关注通过Elasticsearch能做什么,以及何时会用到这些特性。

最后,Elasticsearch有些选项可以让搜索变得很直观,而不仅仅是精确匹配用户的输入。当用户录入与已存储词有所不同的错误拼写、同义词或派生词时,这些选项使用起来非常方便。当用户不完全清楚搜索什么的时候,这些选项也能帮到他们。

1.处理错误的拼写

可以通过配置,让Elasticsearch容忍一些变化,而不仅仅是只查找精确匹配。使用模糊查询,“bicycel”的输入同样可以让用户找到关于“bicycles”的博客。在第6章中,我们将会深入研究模糊查询和其他相关性的特性。

2.支持变体

使用第5章中阐述的分析模块可以让Elasticsearch明白这个道理:标题里包含“bicycle”的帖子,同样可以和“bicyclist”或“cycling”的查询匹配上。你可能已经注意到,在图1-1中,“elections”同样会匹配“election”。你还会注意到,匹配的单词会通过加粗来突显。Elasticsearch同样可以实现这个功能,在附录C中将讨论高亮功能。

3.使用统计信息

当用户不太清楚具体要搜索什么的时候,可以通过几种方式来协助他们。一种方法是第7章探讨的聚集统计数据。聚集是在搜索结果里得到一些统计数据,如每个分类有多少议题、每个分类中“赞”和“分享”的平均数量。假想一下,进入博客时,用户会在右侧看见最近流行的议题。其中之一是自行车。对其感兴趣的读者会点击这个标题,进一步缩小范围。然后,可能还有另外的聚集方式,将自行车相关的帖子分为“自行车鉴赏”“自行车大事件”等。

4.给予自动提示

当用户开始输入时,你可以帮助他们发现主流的查询和结果。还可以通过自动提示技术预测他们所要输入的内容,就像Web上很多搜索引擎做的那样。你同样可以展示主流的结果,通过特殊的查询类型来匹配前缀、通配符或正则表达式。附录F中会讨论建议器(suggester),与普通的查询自动完成功能相比,建议器速度更快。

既然已经讨论了Elasticsearch的整体功能,接下来就来看看在实际产品中这些功能是如何使用的。

我们已经可以确定,在Elasticsearch中存储和索引数据,是提供快速和相关查询结果的上佳方法。但是归根结底,Elasticsearch只是个搜索引擎,你永远不可能单独使用它。就像其他数据存储,需要通过某种方式将数据输入到其中,也可能需要提供用户搜索数据的交互界面。

为了理解Elasticsearch是如何融入更大的系统中的,来考虑以下3种典型的应用场景。

让我们仔细查看一下每个应用场景。

传统意义上说来,搜索引擎在完善的数据存储的基础之上部署,用于提供快速和相关的搜索能力。这是因为历史上的搜索引擎没有提供持久化存储以及类似统计的其他常用功能。

Elasticsearch是一个现代搜索引擎,提供了持久化存储、统计和很多其他数据存储的特性。如果正在启动一个新项目,我们建议你考虑使用Elasticsearch作为唯一的数据存储,尽量使设计保持简洁。这样做也许不能在所有用例中都行得通,例如,存在很多数据更新的时候。这时你也可以在另一个数据存储上使用Elasticsearch。

注意

 

就像其他的NoSQL数据存储,Elasticsearch并不支持事务。在第3章中,你将看到如何使用版本控制来管理并发。如果需要事务机制,请考虑使用其他的数据库作为“真实之源”。另外,在使用单一的数据源时,定期的备份也是很好的实践,我们将在第11章中探讨备份机制。

回到博客的示例:你可以在Elasticsearch中存储新写的博客帖。类似地,可以使用Elasticsearch来检索、搜索或者在所有数据上进行统计,如图1-2所示。

图1-2 Elasticsearch作为唯一的后端,存储并索引所有的数据

如果一台服务器宕机了会发生什么?可以通过将数据复制到不同的服务器来达到容错的效果。很多其他特性使得Elasticsearch成为一个很有吸引力的NoSQL数据存储。这样做不可能面面俱到,但是你需要权衡一下,在整体设计中引入另一个数据源而增加额外的复杂度,这样做是否值得。

就其本身而言,Elasticsearch也许不会提供你所需的一切数据存储功能。某些场合需要在另一个数据存储的基础上使用Elasticsearch。

例如,目前Elasticsearch还不支持事务和复杂关系的特性,至少在版本1中是如此。如果需要那样的特性,请考虑同时使用Elasticsearch和另一个不同的数据存储。

或者你已经有一个复杂的系统在运作,但是想加入搜索功能。如果只是为了使用Elasticsearch而重新设计整个系统(尽管随着时间的推移你可能有这种想法),那么未免太冒险了。更安全的方法是在系统中加入Elasticsearch,让它和现有模块协同工作。

无论哪种方式,如果你有两个数据存储,必须想方设法保持它们的同步。根据主要数据存储是什么类型的,以及数据是如何布局规划的,可以部署一个Elasticsearch插件,保持两者同步,如图1-3所示。

图1-3 Elasticsearch和另一个数据存储位于同一系统中

举个例子,假设有一家在线零售商店,商品的信息都存在SQL数据库中,需要快速而且相关性良好的搜索,于是安装了Elasticsearch。为了索引数据,需要部署同步的机制,既可以是Elasticsearch的插件,也可以是自行构建的定制化服务。在附录B中你将学习更多关于插件的内容,在第3章中将学习更多通过自己的应用程序进行索引和更新的内容。同步的机制可以将每个商品对应的数据拉取出来,并将其索引到Elasticsearch之中,每个商品存储为一篇Elasticsearch的文档。

当用户在页面上的搜索条件框中输入时,商店的前端网络应用程序根据那些条件查询Elasticsearch。Elasticsearch返回一些符合条件的商品文档,按照你喜欢的方式排序。排序可以基于相关性得分,该得分体现用户查询的关键词在每个商品文档出现的次数,或者是商品文档里存储的任何信息,如商品最近多久上架的、平均的得分甚至是多项因素的综合。

信息的插入或更新仍然可以在“主”SQL数据库上进行,所以你可以使用Elasticsearch仅来处理搜索。保持Elasticsearch更新最近的变化取决于同步的机制。

当需要将Elasticsearch和其他模块集成的时候,可以看看现有的工具哪些已经完成你所想要的。下一部分中将探讨,社区为Elasticsearch构建了一些强大的工具,有些时候没有必要自己构建定制的模块。

在某些用例中,无须编写任何代码,就能让Elasticsearch帮你将任务搞定。很多现成的工具可以和Elasticsearch协同工作,没有必要从头开始。

例如,假设你想部署大规模的日志框架,用于存储、搜索和分析海量的事件。如图1-4所示,为了处理日志,并输出到Elasticsearch,可以使用Rsyslog、Logstash或Apache Flume这样的日志工具。为了通过可视化界面搜索和分析日志,可以使用Kibana。

图1-4 Elasticsearch和另一个数据存储位于同一系统中

事实上,Elasticsearch在Apache 2许可证下是开源的。确切地说,开源不是如此多工具支持Elasticsearch的唯一原因。尽管Elasticsearch是Java编写的,不仅仅是Java API可以和它工作。它也暴露了REST API,任何应用程序,无论是何种编程语言编写的,都可以访问这种接口。

此外,REST请求和结果返回通常是JSON(JavaScript Object Notation)格式的。通常,一个REST请求有其自己的JSON有效载荷,返回结果同样是一个JSON文档。

JSON和YAML

 

JSON是表达数据结构的一种格式。一个JSON对象通常包含键和值,值可以是字符串、数字、真/假、空、另一个对象或数组。

对于应用程序而言,JSON很容易解析和生成。YAML(YAML Ain’t Markup Language)可以达到同样的目的。为了激活YAML,在HTTP请求中添加format=yaml的参数。尽管JSON通常是用于HTTP连接,配置文件常常是以YAML书写。在这本书中,我们坚持使用流行的格式:HTTP连接使用JSON,配置文件使用YAML。

举个例子,在Elasticsearch中进行索引时,一条日志事件可能是这样的:

{
 "message": "logging to Elasticsearch for the first time",   ←---一个拥有字符串值的字段
 "timestamp": "2013-08-05T10:34:00" ←---字符串值可以是一个日期,Elasticsearch会自动评估
}

注意

 

在全书中,JSON字段名称显示为深灰色,它们的值显示为浅灰色,以此使得代码更容易阅读。

一个message值为first的日志搜索请求会是这样:

    {
     "query": {
      "match": {   ←---query 字段的值是一个包含match 字段的对象
       "message": "first"   ←---match 字段包含另一个对象,该对象中message 字段的值是first
      }
     }
    }

通过HTTP上的JSON对象来发送数据、运行查询,这样可以更容易地扩展任何事物,从Rsyslog这样的系统日志守护进程到Apache ManifoldCF这样的连接框架,让它们和Elasticsearch进行交互。如果从头开始构建一个新的应用,或是将搜索功能加入现有的应用,REST API是一个使得Elasticsearch变得更吸引人的特性。我们将在下一部分中了解这些特性。

Elasticsearch让你可以轻松地使用Lucene的索引功能,并搜索数据。在索引步骤中,有许多的选项,可以设置如何处理文本、如何存储处理后的文本。在搜索的时候,有很多查询和过滤器供选择。Elasticsearch通过REST API显露了很多功能,让用户可以构建JSON格式的查询、调整大多数的配置。

在Lucene提供的功能之上,Elasticsearch添加了其自己的高级功能,从缓存到实时性分析。在第7章中,你将学习如何通过聚集功能进行分析,借此获得最流行的博客标签、一组帖子的平均流行度,以及任意的组合,如每类标签中帖子的平均流行度。

另一种抽象层次是组织文档的方式:多个索引可以单独搜索、也可以同时搜索,还可以将不同类型的文档放入不同的索引。

最终,Elasticsearch就像它的名字一样,是具有灵活性的。默认它就是集群化的(即使是在单台服务器上运行,也称之为集群),并且总是可以添加更多的服务器用于增加容量或容错性。类似地,如果负载较低的时候,可以很容易地从集群中移除服务器,降低成本。

在本书余下的部分,我们将讨论这些特性的大量细节(特别是第9章的扩展),在此之前,先来近距离观察下这些特性是如何起到作用的。

在很多用例中,用户会基于多项条件进行搜索。例如,可以在多个字段中搜索多个关键词;一些条件是必需的,一些条件是可选的。Elasticsearch最为人赏识的一个特性是结构合理的REST API:可以通过JSON构建查询,使用很多方式来结合不同类型的查询。在第4章中我们将展示如何做到这些,读者还将理解如何使用过滤器,以低成本和可缓存的方式去包含和排除搜索结果。基于JSON的搜索可以同时包含查询、过滤器和聚集,聚集从匹配的文档中生成统计数据。

通过同样的REST API,可以读取和改变很多设置(将在第11章介绍),包括文档索引的方式。

什么是Apache Solr

 

如果你已经听说过Lucene,那么可能你也听说了Solr,它是开源的基于Lucene的分布式搜索引擎。实际上,Lucene和Solr于2010年合并为一个单独的Apache项目,你可能好奇Elasticsearch和Solr两者相比孰优孰劣。

两者都提供了相似的功能,每个新版本中特性都快速地进化。可以通过互联网查找它们的对比,但是我们建议持保留态度。除了受限于特定版本(这种比较几个月之内就会过时),很多观点出于种种原因也都是有所偏见的。

即便如此,还是有一些历史事实有助于解释两个产品的起源。Solr诞生于2004年,而Elasticsearch诞生于2010年。当Elasticsearch出现的时候,它采用的分布式模式(本章稍后介绍)使它相比其竞争对手而言更容易水平扩展,这也印证了它名字中的“elastic”。但是,Solr与此同时在版本4.0中加入了分片,因而“分布式”的说法值得商榷,就像很多其他方面一样。

在本书撰写的时候,Elasticsearch和Solr都拥有对方所不具备的特性,对于它们的选择取决于在特定时期所需要的具体功能。对于很多用例而言,你所需的功能两者都已提供。和很多竞品选择一样,它们之间的选择往往变成了个人口味问题。如果想阅读更多关于Solr的内容,我们推荐Trey Grainger和Timothy Potter所著的《Solr实战》(Manning,2014)。

当考虑文档索引的方式时,一个重要的方面是分析。通过分析,被索引文本中的单词变为Elasticsearch中的词条。例如,如果索引文本“bicycle race”,分析步骤将产生“bicycle”“race”“cycling”和“racing”的词条。当搜索其中任一词条,相应的文档就会被返回。当进行搜索时,会应用同样的分析过程,如图1-5所示。如果输入“bicycle race”,你可能不想仅仅是字符串的严格匹配。也许某个文档,在不同的位置分别出现这两个关键词,它也是符合要求的。

图1-5 在你进行索引和搜索的时候,分析步骤将文本拆解为单词

默认的分析器首先通过空格和逗号这样的常用单词分隔符,将文本拆解为单词。然后将其转化为小写,这样“Bicycle Race”变为“bicycle”和“race”。有很多分析器供选择,你也可以自行构建。第5章将讨论这些。

目前,图1-5中“被索引的数据”方框看上去非常抽象,你可能想知道其中有些什么。正如接下来所探讨的,数据以文档的形式组织。默认情况下,Elasticsearch原封不动地保存文档,并将分析出的词条放入倒排索引,使得所有重要、快速且相关性良好的搜索成为可能。在第3章中,我们深入数据索引和存储的细节。现在,先来近距离观察一下,为什么Elasticsearch是面向文档的,它又是如何将文档按照类型和索引来组织的。

关系型数据库以记录和行的形式存储数据。和关系型数据库不同,Elasticsearch以文档的形式存储数据。然而,某种程度上说,两个概念是相似的。关系型数据表的行都有很多列,每一行的每一列拥有一个值。每个文档拥有键和值,方式差不多。

区别在于,至少在Elasticsearch中,文档比数据表的行更为灵活。这主要是因为文档可以是具有层次型的。例如,"author":"Joe"这样的键和字符串值关联方式,同样可以用于文档中关联字符串数组,如"tags ":["cycling", "bicycles"],甚至是键值对,如"author": {"first_name":"Joe", "last_name":"Smith"}。这种灵活性是非常重要的,因为它鼓励你将所有属于一个逻辑实体的数据保持在同一个文档中,而不是让它们散落在不同的数据表的不同行中。例如,最容易的(可能也是最快的)博客文章存储方式是将某篇帖子的所有数据保持在同一个文档中。使用这种方式,搜索是很快速的,因为无须进行表的连接或其他关系型的工作。

如果你有SQL的知识背景,可能会怀念表连接的功能。但至少1.76版本的Elasticsearch中是不支持此项功能的。不过,即使新增了这个功能,通常只需要下载最新版,就能让Elasticsearch再次运行起来。

如果还没有Java Runtime Environment(JRE),需要先安装它。任何1.7或更新版本的JRE都是可以的。通常,人们会安装从Oracle下载的版本,或者是开源的实现版OpenJDK。

“没有发现Java”错误的排除

 

在Elasticsearch或其他Java应用程序中,可能会发生这样的情况:你已经下载并安装了Java,但是应用程序没能启动,并提示无法发现Java。

Elasticsearch的脚本通过两种方式查找Java的安装:JAVA_HOME环境变量和系统路径。要检查Java安装目录是否在JAVA_HOME中,在UNIX类系统中使用env命令,在Windows系统中使用set命令。要检查是否在系统路径中,运行如下命令:% java -version

如果生效了,那么Java就已经配置在路径之中。如果不行,要么配置JAVA_HOME,要么将Java运行包添加到路径中。Java的运行包通常在Java安装路径(应该就是JAVA_HOME)的bin目录中。

当Java设置完毕,需要获得Elasticsearch并启动它。请下载最适合你工作环境的安装包。在Elastic官方网站上可用的安装包选项有Tar、ZIP、RPM和DEB。

1.任何UNIX类的操作系统

如果在Linux、Mac或其他任何UNIX类的操作系统上运行,可以从tar.gz包获得Elasticsearch。然后将安装包展开,通过压缩包中的shell脚本来启动Elasticsearch。

% tar zxf elasticsearch-*.tar.gz
% cd elasticsearch-*
% bin/elasticsearch

2.用于OS X系统的Homebrew安装包管理器

如果需要在Mac上使用更简单的方式来安装Elasticsearch,可以安装Homebrew。Homebrew 安装完毕运行如下命令就可以获得Elasticsearch:

% brew install elasticsearch

然后,使用和tar.gz压缩包类似的方式开始启动Elasticsearch:

% elasticsearch

3.ZIP压缩包

如果是在Windows上运行,请下载ZIP压缩包。解压后,和在UNIX上运行Elasticsearch差不多,运行bin/目录中的elasticsearch.bat:

% bin\elasticsearch.bat

4.RPM或者DEB压缩包

如果是在Red Hat Linux、CentOS、SUSE或任何可以读取RPM包的系统上运行,在Debian、Ubuntu或任何可以读取DEB包的系统上运行,Elastic同样也提供RPM和DEB包。你可以在www.elastic.co/guide/en/elasticsearch/reference/current/setup-repositories.html学习如何使用它们。

安装的过程基本上需要将安装包加入你的列表中,并运行安装命令。一旦Elasticsearch安装完成,可以通过如下命令启动它:

% systemctl start elasticsearch.service

如果操作系统没有systemd软件,请使用:

% /etc/init.d/elasticsearch start

如果想知道启动后Elasticsearch在干什么,请查看/var/log/elasticsearch/目录中的日志文件。如果是通过解压TAR或ZIP压缩包来安装的,你应该在解压的logs/目录中可以找到日志文件。

现在已经安装并启动了Elasticsearch,我们来看看启动过程中产生的日志,并首次连接REST API。

1.查看启动日志

在首次运行Elasticsearch的时候,用户会看到一系列日志条目,告诉用户发生了什么。来看看其中的几行意味着什么。

第一行通常提供了启动节点的统计信息:

[node] [Karkas] version[1.4.0], pid[6011], build[bc94bd8/2014-11-05T14:26:12Z]

默认情况下,Elasticsearch为节点随机分配一个名字,在这个例子中是Karkas,可以在配置中修改。此行还可以看见所运行的特定Elasticsearch版本号细节,然后是所启动的Java进程PID。

插件在初始化过程中被加载,默认情况下是没有插件的。

[plugins] [Karkas] loaded [], sites []

关于插件的更多信息,请参见附录B。

端口9300默认用于节点之间的通信,称为transport:

[transport] [Karkas] bound_address {inet[/0.0.0.0:9300]}, publish_address
{inet[/192.168.1.8:9300]}

如果使用本地Java API而不是REST API,需要连接这个端口。

在下一行,主节点被选举出来,正是名为Karkas的节点:

[cluster.service] [Karkas] new_master [Karkas][YPHC_vWiQVuSX-ZIJIlMhg][inet[/ 
192.168.1.8:9300]], reason: zen-disco-join (elected_as_master)

第9章涵盖了水平扩展的内容,我们在第9章讨论主节点的选举。基本的想法是每个集群拥有一个主节点,负责了解集群中有哪些节点以及分片位于哪里。每当主节点失联,就会选举一个新的主节点。这个例子中,你启动了集群中的第一个节点,所以它也是主节点。

端口9200默认用于HTTP的通信。应用程序使用REST API时连接这个端口:

[http] [Karkas] bound_address {inet[/0.0.0.0:9200]}, publish_address {inet[/
192.168.1.8:9200]}

下面这一行意味着节点已经启动:

[node] [Karkas] started

现在,可以连接到该节点并开始发送请求。

下面的gateway是负责将数据持久化到磁盘的Elasticsearch组件,这样就不会在节点宕机的时候丢失数据。

[gateway] [Karkas] recovered [0] indices into cluster_state

启动节点之后,gateway将查看磁盘来判断是否有数据在意外时保存过,这样可以恢复这些数据。目前这个例子没有索引需要恢复。

刚刚看的这些日志中,很多信息都是可以配置的,从节点名称到gateway的设置。随着全书内容的展开,我们会谈论配置的选项和相关的概念。第二部分都是关于性能和管理的内容,其中会看到配置的选项。在此之前,无需过多的配置,因为默认的值对于开发者而言非常友好。

警告

 

默认的取值对开发者过于友好了,以至于在同个多播网络中的另一台计算机上,启动一个新的Elasticsearch实例时,该实例会和第一个实例加入同一个集群,可能会导致无法预见的结果。例如,分片从一个节点迁移到另一个节点。为了防止这些发生,可以在elasticsearch.yml配置文件中修改集群的名称,2.5.1节会演示如何操作。

2.使用REST API

连接REST API最简单的方法是在浏览器里导航到http://localhost:9200。如果不是在本机上安装Elasticsearch,那么需要将localhost替换为远程机器的IP地址。Elasticsearch默认监听从9200端口进入的HTTP请求。如果请求生效了,用户应该获得一个JSON应答,这也表明Elasticsearch正常工作,如图1-6所示。

图1-6 在浏览器中检阅Elasticsearch

现在一切设置完毕,让我们回顾一下本章讨论的内容:

在第2章中,读者将通过索引和搜索真实的数据,加深对Elasticsearch的了解。


相关图书

Rust游戏开发实战
Rust游戏开发实战
仓颉编程快速上手
仓颉编程快速上手
深入浅出Go语言编程从原理解析到实战进阶
深入浅出Go语言编程从原理解析到实战进阶
JUnit实战(第3版)
JUnit实战(第3版)
Go语言编程指南
Go语言编程指南
Scala速学版(第3版)
Scala速学版(第3版)

相关文章

相关课程