比特派钱包官网注册|elasticsearch

作者: 比特派钱包官网注册
2024-03-07 18:29:33

Elasticsearch:官方分布式搜索和分析引擎 | Elastic

ticsearch:官方分布式搜索和分析引擎 | ElasticSkip to main contentPlatformPlatform解决方案解决方案客户客户资源资源定价定价文档文档Language pickerDeutschEnglishEspañolFrançais日本語한국어简体中文PortuguêsSearchLogin开始免费试用联系销售人员Elasticsearch Platform可观测性、安全和搜索等三大解决方案 — 由 Elasticsearch 平台提供支持。Elastic 概述ELK Stack搜索和分析、数据采集以及可视化,易如反掌KibanaElasticsearch集成ELK Stack 概述Elastic Cloud在您首选的云服务提供商平台上利用 Elastic 找到重要答案。Cloud 概述合作伙伴联系销售人员可观测性一体化实现应用和基础架构可见性,主动解决问题。日志监测应用程序性能监测基础架构监测合成监测真实用户监测Universal ProfilingAIOpsOpenTelemetry可观测性概述安全性快速、大规模地防范、调查和应对网络威胁。持续监测威胁猎捕调查和事件响应自动威胁防护安全性概述搜索在任何云中加速搜索结果,并提高个性化程度。生成式 AI搜索应用程序电子商务网站Workplace Search客户支持搜索概述按行业公共领域金融服务电信医疗保健技术零售和电子商务制造和汽车查看所有行业按解决方案让客户能够提升速度、灵活扩展并制定下一步的计划。可观测性安全性搜索客户聚焦了解 Cisco 如何借助 AI 打造搜索体验了解详情了解 RWE 如何为其可再生能源交易业务提供支持了解详情了解 Comcast 如何提高工程速度并加速创新了解详情开发人员深入了解与代码、论坛和群组相关的所有内容。社区论坛下载保持联系及时了解最新科技主题、创新技术和新闻。活动博文学习提高技能,开启未来成功之门。开始使用Elastic 资源咨询服务培训和认证安全实验室帮助无论是什么主题,都能找到所需的支持。联系我们支持中心了解 Elastic 的最新动态查看我们的演示库了解详情Elasticsearch 入门马上观看 Elastic 8.12 版的新功能了解详情SearchPlatformElasticsearch Platform可观测性、安全和搜索等三大解决方案 — 由 Elasticsearch 平台提供支持。Elastic 概述ELK Stack搜索和分析、数据采集以及可视化,易如反掌KibanaElasticsearch集成ELK Stack 概述Elastic Cloud在您首选的云服务提供商平台上利用 Elastic 找到重要答案。Cloud 概述合作伙伴联系销售人员解决方案可观测性一体化实现应用和基础架构可见性,主动解决问题。日志监测应用程序性能监测基础架构监测合成监测真实用户监测Universal ProfilingAIOpsOpenTelemetry可观测性概述安全性快速、大规模地防范、调查和应对网络威胁。持续监测威胁猎捕调查和事件响应自动威胁防护安全性概述搜索在任何云中加速搜索结果,并提高个性化程度。生成式 AI搜索应用程序电子商务网站Workplace Search客户支持搜索概述按行业公共领域金融服务电信医疗保健技术零售和电子商务制造和汽车查看所有行业客户按解决方案让客户能够提升速度、灵活扩展并制定下一步的计划。可观测性安全性搜索客户聚焦了解 Cisco 如何借助 AI 打造搜索体验了解详情了解 RWE 如何为其可再生能源交易业务提供支持了解详情了解 Comcast 如何提高工程速度并加速创新了解详情资源开发人员深入了解与代码、论坛和群组相关的所有内容。社区论坛下载保持联系及时了解最新科技主题、创新技术和新闻。活动博文学习提高技能,开启未来成功之门。开始使用Elastic 资源咨询服务培训和认证安全实验室帮助无论是什么主题,都能找到所需的支持。联系我们支持中心了解 Elastic 的最新动态查看我们的演示库了解详情Elasticsearch 入门马上观看 Elastic 8.12 版的新功能了解详情定价文档Language picker 语言DeutschEnglishEspañolFrançais日本語한국어简体中文PortuguêsLogin 登录开始免费试用联系销售人员Elastic Stack功能功能Stack 安全性Machine Learning地理空间Elasticsearch概述功能Elasticsearch ServiceElasticsearch 可搜索快照Elasticsearch 运行时字段Kibana概述功能Kibana CanvasKibana LensKibana 仪表板Kibana AlertingElastic MapsElastic Maps Service集成概述数据集成Elastic 代理BeatsLogstash网络爬虫内容连接器文档Elasticsearch免费且开放的 Elastic Stack 的核心所在Elasticsearch 是一个分布式、RESTful 风格的搜索和数据分析引擎,能够解决不断涌现出的各种用例。作为 Elastic Stack 的核心,Elasticsearch 会集中存储您的数据,让您飞快完成搜索,微调相关性,进行强大的分析,并轻松缩放规模。开始免费试用查看网络研讨会下载 Elasticsearch刚接触 Elasticsearch?立即部署并运行。观看视频参加我们的 Elasticsearch 工程师培训,为使用 Elasticsearch 奠定良好的基础。查看培训培养高级 Elasicsearch 技能,例如相关度调整、文本分析等等。查看培训新增功能Elasticsearch 查询语言 (ES|QL) 可转换和简化数据调查。ES|QL 引擎提供了高级搜索功能,通过搜索和简化的工作流程来提高效率和加速解决问题。了解详情深入了解全新 Elasticsearch Relevance EngineElasticsearch Relevance Engine™ (ESRE) 旨在为基于人工智能的搜索应用程序提供强大支持。使用 ESRE,您可以应用具有卓越相关性的开箱即用型语义搜索(无需域适应),与外部大型语言模型 (LLM) 集成,实现混合搜索,并使用第三方或您自己的转换器模型。查询和分析从数据中探寻各种问题的答案定义您自己的搜索方式通过 Elasticsearch,您能够执行和合并多种类型的搜索(结构化数据、非结构化数据、地理位置、指标,以及从管道查询语言搜索)。先从一个简单的问题开始,看看能够从中发现些什么。分析大规模数据找到与查询最匹配的 10 个文档并不困难。但如果面对的是十亿行日志,又该如何解读呢?Elasticsearch 聚合让您能够从大处着眼,探索数据的趋势和规律。速度Elasticsearch 很快,快到不可思议快速获得结果如果您能够立即获得答案,您与数据的关系就会发生变化。这样您就有条件进行迭代并涵盖更大的范围。 

强大的设计但是要达到这样的速度并非易事。我们通过有限状态转换器实现了用于全文检索的倒排索引,实现了用于存储数值数据和地理位置数据的 BKD 树,以及用于分析的列存储。

无所不包而且由于每个数据都被编入了索引,因此您再也不用因为某些数据没有索引而烦心。您可以用快到令人惊叹的速度使用和访问您的所有数据。可扩展性可以在笔记本电脑上运行。也可以在承载了 PB 级数据的成百上千台服务器上运行。原型环境和生产环境可无缝切换;无论 Elasticsearch 是在一个节点上运行,还是在一个包含 300 个节点的集群上运行,您都能够以相同的方式与 Elasticsearch 进行通信。

它能够水平扩展,每秒钟可处理海量事件,同时能够自动管理索引和查询在集群中的分布方式,以实现极其流畅的操作。

弹性我们在您高飞的时候保驾护航硬件故障。网络分割。Elasticsearch 为您检测这些故障并确保您的集群(和数据)的安全性和可用性。通过跨集群复制功能,辅助集群可以作为热备份随时投入使用。Elasticsearch 运行在一个分布式的环境中,从设计之初就考虑到了这一点,目的只有一个,让您永远高枕无忧。

灵活性存储和探索数据以满足自身需求。数据是不断变化的,这使得存储和搜索全部数据变得非常昂贵。Elasticsearch 能让您在性能和成本之间取得平衡。您可以将数据存储在本地以实现快速查询,也可以将无限量的数据远程存储于低成本的 S3 上。借助运行时字段,您还可以快速加载数据并针对变化做出相应调整。

用例我到底能够使用 Elasticsearch 做什么?数字、文本、地理位置、结构化数据、非结构化数据。适用于所有数据类型。全文本搜索只是全球众多公司利用 Elasticsearch 解决各种挑战的冰山一角。查看直接依托 Elastic Stack 所构建解决方案的完整列表。

日志监测快速且可扩展的日志管理,绝不会让您失望。基础架构监测对您的系统指标进行监测和可视化。APM深入洞察应用程序的性能。合成监测监测可用性问题并进行应对。企业搜索提升任何用例的搜索和发现体验。Maps实时探索位置数据。 

SIEM交互式调查和自动威胁检测。终端安全预防、检测、猎捕并应对威胁。下列客户已在使用,并深受他们的信任和喜爱分布式您的部署您做主无论您在哪里进行搜索,我们都能满足您的需求。

Elastic Cloud 的业务价值在 AWS、Google Cloud 和 Azure 上部署托管型 Elasticsearch 和 Kibana在您所选的云服务提供商平台上迅速完成全套技术栈的部署。作为 Elasticsearch 的开发公司,我们为您在云端的 Elastic 集群提供多项功能和贴心支持。查看定价开始免费试用本地部署下载 Elasticsearch安装最新版本后,只需几步即可开始在您的设备上运行 Elasticsearch。

下载真正的 Elasticsearch 体验它与 Amazon 的 Elasticsearch Service 一样吗?不一样,仅此一家。由开发人员直接推出,我们的 Elasticsearch Service 是 AWS 上唯一的官方托管型 Elasticsearch 产品。

专属功能使用多项专属功能,例如 Machine Learning、针对 BI 连接性的 ODBC 驱动程序、时序数据自动管理以及 Alerting。改善Elasticsearch 功能探索完整的 Elasticsearch 功能列表。安全性为您的 Elasticsearch 数据提供强大、细致的保护。了解详情Monitoring随时了解 Elastic Stack 的动态,确保其处于最佳状态。了解详情Alerting在数据发生变化时及时收到通知。 

了解详情Elasticsearch SQL使用 SQL 与您的数据进行交互,还可使用 ODBC 和 JDBC 驱动程序访问这些数据。了解详情时序数据管理通过索引生命周期管理、冻结索引和汇总等方式,自动完成进程。了解详情Machine Learning自动对 Elasticsearch 数据进行异常检测。了解详情客户端库使用您自由选择的编程语言与 Elasticsearch 进行交互Elasticsearch 使用的是标准的 RESTful 风格的 API 和 JSON。此外,我们还构建和维护了很多其他语言的客户端,例如 Java、Python、.NET、SQL 和 PHP。与此同时,我们的社区也贡献了很多客户端。这些客户端使用起来简单自然,而且就像 Elasticsearch 一样,不会对您的使用方式进行限制。

CurlC#GoJavaJavaScriptPerlPHPPythonRubySQLcurl -H "Content-Type: application/json" -XGET

'http://localhost:9200/social-*/_search' -d '{

"query": {

"match": {

"message": "myProduct"

}

},

"aggregations": {

"top_10_states": {

"terms": {

"field": "state",

"size": 10

}

}

}

}'了解 Elasticsearch本次网络研讨会将介绍如何上手使用,包括如何在 Elasticsearch 中部署、管理和分析数据。开始使用关注我们关于我们关于 Elastic发展历程领导团队DE&I博文加入我们招贤纳士招聘门户新闻稿新闻发布稿新闻文章合作伙伴寻找合作伙伴合作伙伴登录申请访问权限成为合作伙伴信任和安全性EthicsPoint 门户安全和隐私ECCN 报告道德准则邮件投资者关系投资者资源治理金融股票卓越奖往届获奖者ElasticON 之旅成为赞助商所有活动关于我们关于 Elastic发展历程领导团队DE&I博文加入我们招贤纳士招聘门户新闻稿新闻发布稿新闻文章合作伙伴寻找合作伙伴合作伙伴登录申请访问权限成为合作伙伴信任和安全性EthicsPoint 门户安全和隐私ECCN 报告道德准则邮件投资者关系投资者资源治理金融股票卓越奖往届获奖者ElasticON 之旅成为赞助商所有活动商标使用条款隐私网站地图© .Elasticsearch B.V.保留所有权利Elastic、Elasticsearch 及其他相关标志为 Elasticsearch B.V. 在美国和其他国家/地区的商标、徽标或注册商标。Apache、Apache Lucene、Apache Hadoop、Hadoop、HDFS 和黄色大象徽标是 Apache 软件基金会的注册商标,已在美国和/或其他国家/地区

从 0 到 1 学习 elasticsearch ,这一篇就够了!(建议收藏) - 知乎

从 0 到 1 学习 elasticsearch ,这一篇就够了!(建议收藏) - 知乎首发于大数据技术切换模式写文章登录/注册从 0 到 1 学习 elasticsearch ,这一篇就够了!(建议收藏)大数据梦想家本文已收录github:https://github.com/BigDataScholar/TheKingOfBigData,里面有我准备的大数据高频考点,Java一线大厂面试题资源,上百本免费电子书籍,作者亲绘大数据生态圈思维导图…持续更新,欢迎star! 前言 之前一直想花点时间写一篇 elasticsearch 的保姆级教程,于是,趁着年假的几天时间加上周末的一些时间,我产出了自认为算是非常详细的,基于目前最新版本的elasticsearch7.11教程。不管是新手上路,还是秋名山老司机,都建议收藏一下,希望看完对您有所帮助!如果可以,记得一键三连! 目录:前言ElasticSearch概述ES 和 solr 的差别Elasticsearch 简介Solr 简介Lucene简介Elasticsearch和Solr比较ElasticSearch vs Solr 总结安装elasticsearch上传安装包到linux并解压目录结构修改配置文件添加用户启动es启动与暂停安装elasticsearch-head(方法1)安装npm安装cnpm下载依赖安装elasticsearch-head(方法2)安装Kibana了解ELKKibana的安装踩坑ES的核心概念概述对比文档类型索引倒排索引ES基础操作IK 分词器Rest风格说明关于索引的基本操作关于文档的基本操作小结巨人的肩膀彩蛋ElasticSearch概述 Elaticsearch,简称为es, es是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理PB级别的数据。es也使用Java开发并使用 Lucene 作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的 RESTful API 来隐藏 Lucene 的复杂性,从而让全文搜索变得简单。 据国际权威的数据库产品评测机构 DB Engines 的统计,在2016年1月,ElasticSearch已超过Solr等,成为排名第一的搜索引擎类应用。 为了增加学习的趣味性,我们来聊一聊 elasticsearch 的历史历史 多年前,一个叫做Shay Banon的刚结婚不久的失业开发者,由于妻子要去伦敦学习厨师,他便跟着也去了。在他找工作的过程中,为了给妻子构建一个食谱的搜索引擎,他开始构建一个早期版本的Lucene。 直接基于Lucene工作会比较困难,所以Shay开始抽象Lucene代码以便Java程序员可以在应用中添加搜索功能。他发布了他的第一个开源项目,叫做“Compass”。 后来Shay找到一份工作,这份工作处在高性能和内存数据网格的分布式环境中,因此高性能的、实时的、分布式的搜索引擎也是理所当然需要的。然后他决定重写Compass库使其成为一个独立的服务叫做Elasticsearch。 第一个公开版本出现在2010年2月,在那之后Elasticsearch已经成为Github上最受欢迎的项目之一,代码贡献者超过300人。一家主营Elasticsearch的公司就此成立,他们一边提供商业支持一边开发新功能,不过 Elasticsearch 将永远开源且对所有人可用。 Shay的妻子依旧等待着她的食谱搜索……ES 和 solr 的差别 学习 ES,我们免不了需要跟 solr 进行对比学习!下面我们分别来看看,它们之间具体的差别在哪里:Elasticsearch 简介Elasticsearch 是一个实时分布式搜索和分析引擎。它让你以前所未有的速度处理大数据成为可能。 它用于全文搜索、结构化搜索、分析以及将这三者混合使用: 维基百科使用Elasticsearch提供全文搜索并高亮关键字,以及输入 实时搜索(search-asyou-type)和 搜索纠错(did-you-mean)等搜索建议功能。 英国卫报使用Elasticsearch结合用户日志和社交网络数据提供给他们的编辑以实时的反馈,以便及时了解公众对新发表的文章的回应。 StackOverflow结合全文搜索与地理位置查询,以及more-like-this功能来找到相关的问题和答案。 Github使用Elasticsearch检索1300亿行的代码。 但是 Elasticsearch 不仅用于大型企业,它还让像DataDog 以及 Klout 这样的创业公司将最初的想法变成可扩展的解决方案。Elasticsearch可以在你的笔记本上运行,也可以在数以百计的服务器上处理PB级别的数据 。 Elasticsearch 是一个基于 Apache Lucene(TM) 的开源搜索引擎。无论在开源还是专有领域,Lucene可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库 但是,Lucene只是一个库。想要使用它,你必须使用Java来作为开发语言并将其直接集成到你的应用中,更糟糕的是,Lucene非常复杂,你需要深入了解检索的相关知识来理解它是如何工作的 Elasticsearch也使用Java开发并使用 Lucene 作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的 RESTful API 来隐藏 Lucene 的复杂性,从而让全文搜索变得简单Solr 简介 Solr 是 Apache 下的一个顶级开源项目,采用Java开发,它是基于 Lucene 的全文搜索服务器。Solr提供了比 Lucene 更为丰富的查询语言,同时实现了可配置、可扩展,并对索引、搜索性能进行了优化。 Solr可以独立运行,运行在Jetty、Tomcat 等这些Servlet容器中,Solr 索引的实现方法很简单,用 POST 方法向 Solr 服务器发送一个描述 Field 及其内容的 XML 文档,Solr根据 xml 文档添加、删除、更新索引。Solr 搜索只需要发送 HTTP GET 请求,然后对 Solr 返回Xml、json等格式的查询结果进行解析,组织页面布局。Solr不提供构建UI的功能,Solr提供了一个管理界面,通过管理界面可以查询Solr的配置和运行情况。 Solr是基于 lucene 开发企业级搜索服务器,实际上就是封装了lucene。 Solr是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口。用户可以通过http请求,向搜索引擎服务器提交一定格式的文件,生成索引;也可以通过提出查找请求,并得到返回结果。Lucene简介Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。 Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。Lucene是一套用于全文检索和搜寻的开源程式库,由Apache软件基金会支持和提供。Lucene提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻。在Java开发环境里Lucene是一个成熟的免费开源工具。就其本身而言,Lucene是当前以及最近几年最受欢迎的免费Java信息检索程序库。人们经常提到信息检索程序库,虽然与搜索引擎有关,但不应该将信息检索程序库与搜索引擎相混淆。 Lucene是一个全文检索引擎的架构。那什么是全文搜索引擎? 全文搜索引擎是名副其实的搜索引擎,国外具代表性的有Google、Fast/AllTheWeb、AltaVista、Inktomi、Teoma、WiseNut等,国内著名的有百度(Baidu)。它们都是通过从互联网上提取的各个网站的信息(以网页文字为主)而建立的数据库中,检索与用户查询条件匹配的相关记录,然后按一定的排列顺序将结果返回给用户,因此他们是真正的搜索引擎。 从搜索结果来源的角度,全文搜索引擎又可细分为两种,一种是拥有自己的检索程序(Indexer),俗称“蜘蛛”(Spider)程序或“机器人”(Robot)程序,并自建网页数据库,搜索结果直接从自身的数据库中调用,如上面提到的7家引擎;另一种则是租用其他引擎的数据库,并按自定的格式排列搜索结果,如 Lycos 引擎。Elasticsearch和Solr比较ElasticSearch vs Solr 总结 1、es基本是开箱即用,非常简单。Solr安装略微复杂一丢丢! 2、Solr 利用 Zookeeper 进行分布式管理,而 Elasticsearch 自身带有分布式协调管理功能。 3、Solr 支持更多格式的数据,比如JSON、XML、CSV,而 Elasticsearch 仅支持json文件格式 4、Solr 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提供,例如图形化界面需要kibana友好支撑 5、Solr 查询快,但更新索引时慢(即插入删除慢),用于电商等查询多的应用;ES建立索引快(即查询慢),即实时性查询快,用于facebook新浪等搜索。Solr 是传统搜索应用的有力解决方案,但 Elasticsearch 更适用于新兴的实时搜索应用。 6、Solr 比较成熟,有一个更大,更成熟的用户、开发和贡献者社区,而 Elasticsearch 相对开发维护者较少,更新太快,学习使用成本较高。 所以如果我们在做技术选型的时候,具体选择哪一项技术,还需要根据不同的场景来进行结合选择。 哈哈哈,好像跑题了,下面我们就正式进入到 elasticsearch 的学习中!安装elasticsearch 我们首先来到 es 的官网,根据自己不同的操作系统,点击即可下载最新版本的产品,目前最新版本是Elasticsearch 7.11 官网地址:https://www.elastic.co/cn/start Kibana 是一个免费且开放的用户平台,能够让我们对 Elasticsearch 数据进行可视化,这里我们也一并将其下载到本地 上传安装包到linux并解压 我的习惯是将所有的软件包放到/export/software目录下,解压后的目录是/export/servers[root@node01 software]# tar -zxvf elasticsearch-7.11.0-linux-x86_64.tar.gz -C ../servers/

目录结构 解压完毕之后,我们先来熟悉es的目录结构[root@node01 elasticsearch-7.11.0]# ll /export/servers/elasticsearch-7.11.0

总用量 556

drwxr-xr-x. 2 esuser esuser 4096 2月 9 06:48 bin

drwxr-xr-x. 3 esuser esuser 199 2月 13 14:44 config

drwxr-xr-x. 3 esuser esuser 19 2月 13 14:15 data

drwxr-xr-x. 9 esuser esuser 107 2月 9 06:48 jdk

drwxr-xr-x. 3 esuser esuser 4096 2月 9 06:48 lib

-rw-r--r--. 1 esuser esuser 3860 2月 9 06:41 LICENSE.txt

drwxr-xr-x. 2 esuser esuser 6 2月 13 14:47 logs

drwxr-xr-x. 57 esuser esuser 4096 2月 9 06:49 modules

-rw-r--r--. 1 esuser esuser 544318 2月 9 06:46 NOTICE.txt

drwxr-xr-x. 2 esuser esuser 6 2月 9 06:45 plugins

-rw-r--r--. 1 esuser esuser 7263 2月 9 06:41 README.asciidoc

其中我们常用的目录有:bin:可执行文件在里面,运行es的命令就在这个里面,包含了一些脚本文件等config:配置文件目录JDK:java环境lib:依赖的jar,类库logs:日志文件modules:es相关的模块plugins:可以自己开发的插件data:这个目录没有,自己新建一下,后面要用 -> mkdir data,这个作为索引目录修改配置文件 熟悉完es的目录,在启动es前,我们还需要修改一些配置文件核心配置文件 elasticearch.yml[root@node01 elasticsearch-7.11.0]# vim config/elasticsearch.yml

修改集群名称修改当前的 es 节点名称修改data数据保存地址和日志数据保存地址绑定 es 网络 ip集群节点修改为之前的节点名称 具体位置如下图所示: 修改 jvm 参数 因为 Elasticsearch 是用 Java 语言开发的,所以我们在配置环节一定少不了修改 jvm 的参数[root@node01 elasticsearch-7.11.0]# vim config/jvm.options

根据自己当前操作系统的不同配置,设置不同的大小即可 添加用户 比较有意思的一点是,es不允许使用 root 来操作 es,需要我们添加用户,具体的命令如下:# 1. 创建elsearch用户组及elsearch用户:

groupadd elsearch

useradd elsearch -g elsearch

passwd elsearch# 接下来会输入两次密码

# new password

# retype passwd

# 2. 切换到elsearch用户再启动

su elsearch

启动es 修改完上面2个配置文件,我们切换到bin目录下,通过./elasticsearch启动es 不出意外,应该会报如下错误:ERROR: [3] bootstrap checks failed

[1]: max file descriptors [4096] for elasticsearch process is too low, increase to at least [65535]

[2]: max number of threads [3795] for user [esuser] is too low, increase to at least [4096]

我们只需要将最大的线程数设置大一些即可 我们切换回到root目录修改/etc/security/limits.conf文件 添加以下内容* soft nofile 65536

* hard nofile 131072

* soft nproc 2048

* hard nproc 4096

如下图所示: 修改 /etc/sysctl.conf 增加 vm.max_map_count=262145 修改完成之后,使用sysctl -p命令刷新一下,再次切换到 esuser进行启动即可。 记得将防火墙关闭或者将9200端口打开,否则就会出现启动成功,页面无法访问的情况 启动与暂停 启动与暂停这里也分成2种形式启动方式1 我们在bin目录下直接./elasticsearch,可以看到运行结果 然后根据自己的 ip:9200进行访问,可以在界面上看到如下返回的结果 当前启动方式是前端启动。停止服务的话直接ctrl+c 就好了启动方式2 同时,我们也可以后端启动[esuser@node01 bin]$ ./elasticsearch -d

稍等片刻,再次访问地址,还是相同结果 此时,如果想关闭服务[esuser@node01 bin]$ ps -ef|grep elasticsearch

esuser 2931 2178 0 15:58 pts/0 00:00:00 grep --color=auto elasticsearch

然后将对应的进程id kill掉即可! 接下来我们需要安装ES的图形化界面插件,也就是elasticsearch-head,这里介绍2种方法,方法1比较麻烦,想省事的同学可以直接划到下方的方法2,利用谷歌插件进行安装,简单高效!安装elasticsearch-head(方法1) elasticsearch-head是一款开源软件,被托管在github上面,所以如果我们要使用它,必须先安装git,通过git获取elasticsearch-head 给大家看下这个项目,已经斩获 7.3K 的start,说明还是非常受大众欢迎 我们很容易的通过 git 将其clone到本地,然后上传到 linux 服务器上,然后解压。 需要注意的是, 运行elasticsearch-head会用到 grunt,而 grunt 需要 npm 包管理器,所以 nodejs 是必须要安装的安装npm 当然如果你的环境里已经安装好了npm,那则可以跳过这一步。(1) 安装gccyum install gcc gcc-c++

(2) 下载node国内镜像(推荐)wget https://npm.taobao.org/mirrors/node/v10.14.1/node-v10.14.1-linux-x64.tar.gz

(3) 解压并重命名文件夹 解压tar -xvf node-v10.14.1-linux-x64.tar.gz

然后重命名文件夹mv node-v10.14.1-linux-x64 node

(4) 添加环境变量vi /etc/profile

在文件最后添加以下配置:export NODE_HOME=/export/servers/node

export PATH=$NODE_HOME/bin:$PATH

(5) 刷新配置source /etc/profile

(6) 验证结果node -v

npm -v

能够正确显示版本号即说明 nodejs 环境安装成功 安装cnpm 我们上面谈到的 npm 命令是 node.js 的 npm 插件管理器,也就是下载插件安装插件的管理器。但我们在使用的时候,下载的都是国外服务器很慢会掉线,所以这一步,我们需要安装淘宝的 npm 镜像cnpm。 也非常简单,执行如下命令即可npm install -g cnpm --registry=https://registry.npm.taobao.org

排雷:如果遇到this is a problem related to network connectivity, behind a proxy的异常,执行npm config set proxy null将代理设置为空即可再重试上面的命令即可。 cnpm 正常安装完成之后呢,效果图如下: 下载依赖 现在环境都准备好了,那我们该做些什么呢?其实 GitHub 上都已经写明白了 有多种方式运行 elasticsearch-head ,我们这里需要用的就是如上所示的内置服务器的方式。 我们进入到elasticsearch-head的目录下,执行命令,下载相关的依赖[root@node01 elasticsearch-head]# cnpm install

命令执行完毕之后,我们可以在目录下看到多出了node_modules目录,这就是我们下载好的依赖。 然后在该目录下执行npm run start命令,启动 elasticsearch-head[root@node01 elasticsearch-head]# npm run start

> elasticsearch-head@0.0.0 start /export/servers/elasticsearch-head

> grunt server

Running "connect:server" (connect) task

Waiting forever...

Started connect web server on http://localhost:9100

然后我们就可以在浏览器上通过 ip:9100 访问到如下页面,但是当我们点击连接,在控制台又会出现 Error 信息,这是为什么呢? 真相:由于ES进程和客户端进程端口号不同,存在跨域问题,所以我们要在ES的配置文件中添加如下配置下:[root@node01 elasticsearch-7.11.0]# vim config/elasticsearch.yml

# 跨域配置

http.cors.enabled: true

http.cors.allow-origin: "*"

配置完毕,我们重启ES,重新连接,就能正常看到正常的页面了安装elasticsearch-head(方法2) 不知道大家有没有对于操作到这一步,在想着有没有更简单的方式安装 elasticsearch-head 呢? 当然有,我们在 readme 文件中,发现也可以通过在谷歌浏览器上使用插件的形式来进行安装 elasticsearch-head 我们在谷歌应用商店搜索“elasticsearch-head”插件,然后将其安装,自动添加至谷歌浏览器 然后使用的时候,直接单击这个插件,就可以看见与我们按照上面那么繁杂的步骤所展示一致的界面。 嗯,果然还是这种方法香! 如果是初学的小伙伴,就算成功看到这个页面可能还有点懵,因为现在这个网站上还没有什么东西 我们初学,就把 es 当做一个数据库,可以建立索引(库),文档(库中的数据!) 现在还没有索引,我这里就先创建了一个alice索引 然后就可以在概览栏看见分片信息,索引栏看见自己创建的索引,数据浏览栏看到索引里的所有数据! 另外,elasticsearch-head上也提供了基本查询和复合查询的方式,其中复合查询是以 restful风格发起的请求,并且提交的参数都是格式化后的JSON类型。 当然,大家也可能都看到了,这样的工具我们使用起来也不是很方便,这个 elasticsearch-head 我们一般就把它当做数据展示的工具,不建议利用它来进行数据的查询,我们所有的查询,基本都放在 Kibana 中完成安装Kibana了解ELK ELK是Elasticsearch、Logstash、Kibana三大开源框架首字母大写简称。市面上也被成为 ElasticStack 。其中 Elasticsearch 是一个基于 Lucene、分布式、通过 Restful 方式进行交互的近实时搜索平台框架。像类似百度、谷歌这种大数据全文搜索引擎的场景都可以使用 Elasticsearch 作为底层支持框架,可见 Elasticsearch 提供的搜索能力确实强大,市面上很多时候我们简称Elasticsearch为es。Logstash是 ELK 的中央数据流引擎,用于从不同目标(文件/数据存储/MQ)收集的不同格式数据,经过过滤后支持输出到不同目的地(文件/MQ/redis/elasticsearch/kafka等)。Kibana可以将 elasticsearch 的数据通过友好的页面展示出来,提供实时分析的功能。 看了上面的描述,我们大概心里就已经清楚,ELK 的流程大致就是 收集清理数据 -> 搜索,存储 -> Kibana,如下所示: 市面上很多开发只要提到 ELK 能够一致说出它是一个日志分析架构技术栈 总称,但实际上 ELK 不仅仅适用于日志分析,它还可以支持其它任何数据分析和收集的场景,日志分析和收集只是更具有代表性,并非唯一性。Kibana的安装Kibana是一个针对 Elasticsearch 的开源分析及可视化平台,用来搜索、查看交互存储在 Elasticsearch 索引中的数据。使用 Kibana ,可以通过各种图表进行高级数据分析及展示。Kibana 让海量数据更容易理解。它操作简单,基于浏览器的用户界面可以快速创建仪表板(dashboard)实时显示Elasticsearch 查询动态。设置Kibana非常简单。无需编码或者额外的基础架构,几分钟内就可以完成 Kibana 安装并启动 Elasticsearch 索引监测。 官网地址:https://www.elastic.co/cn/kibana 然后选择对应操作系统的版本,默认安装的就是最新版本的 kibana。注意:kibana 版本 要和 es 的版本一致! 下载完毕后,同样上传到Linux服务器,解压[root@node01 software]# tar -zxvf kibana-7.11.0-linux-x86_64.tar.gz -C ../servers/

修改conf目录下的kibana.yml文件,添加上如下的几行配置 然后切回到 bin 目录下,直接 ./kibana 启动即可,此时通过ip:5601 即可正常访问到页面 英文不好的同学是不是感觉看着有些吃力。其实,kibana 有自带的中文包,就在kibana 的 x-pack/plugins/translations/translations 目录下的 zh-CN.json 我们想要使用,直接打开conf目录下的kibana.yml文件 我们可以看到 kibana 默认的语言是 英文,我们只需要添加使用中文插件即可i18n.locale: "zh-CN"

然后重新启动 kibana ,即可看到效果 踩坑 kibana 启动,可能会遇到这个 bug: Error: Unable to write Kibana UUID file, please check the uuid.server configuration value in kibana.yml and ensure Kibana has sufficient permissions to read / write to this file. Error was: EACCES

解决方案 就是:# 在root下为 为kibana赋权

chown -R elsearch:elsearch /export/servers/kibana-7.6.1-linux-x86_64/

# 修改kibana所在文件夹的权限

chmod 770 /export/servers/kibana-7.6.1-linux-x86_64

# 切换回用户组 elsearch

su elsearch

# 启动

./kibana

ES的核心概念概述 在前面的学习中,我们已经掌握了 es 是什么,同时也把 es 的服务已经安装启动,那么 es 是如何去存储数据,数据结构是什么,又是如何实现搜索的呢?我们先来聊聊 ElasticSearch的相关概念 吧 集群,节点,索引,类型,文档,分片,映射是什么?对比 ElasticSearch 是面向文档的非关系型数据库,下面让我们来看看它与关系型数据库的客观对比! Relational DBElasticsearch elasticsearch(集群)中可以包含多个索引(数据库),每个索引中可以包含多个类型(表),每个类型下又包含多个文档(行),每个文档中又包含多个字段(列)物理设计: elasticsearch 在后台把每个索引划分成多个分片,每份分片可以在集群中的不同服务器间迁移逻辑设计: 一个索引类型中,包含多个文档,比如说文档1,文档2。 当我们索引一篇文档时,可以通过这样的一个顺序找到 它: 索引 ▷ 类型 ▷ 文档ID ,通过这个组合我们就能索引到某个具体的文档。 注意 : ID不必是整数,实际上它是个字符串。文档 之前说 elasticsearch 是面向文档的,那么就意味着索引和搜索数据的最小单位是文档,elasticsearch 中,文档有几个 重要属性 :自我包含,一篇文档同时包含字段和对应的值,也就是同时包含 key:value!可以是层次型的,一个文档中包含自文档,复杂的逻辑实体就是这么来的!其实就是个JSON对象灵活的结构,文档不依赖预先定义的模式,我们知道关系型数据库中,要提前定义字段才能使用,在 elasticsearch 中,对于字段是非常灵活的,有时候,我们可以忽略该字段,或者动态的添加一个新的字段。 尽管我们可以随意的新增或者忽略某个字段,但是,每个字段的类型非常重要,比如一个年龄字段类型,可以是字符串也可以是整形。因为 elasticsearch 会保存字段和类型之间的映射及其他的设置。这种映射具体到每个映射的每种类型,这也是为什么在 elasticsearch 中,类型有时候也称为映射类型。类型 类型是文档的逻辑容器,就像关系型数据库一样,表格是行的容器。 类型中对于字段的定义称为映射,比如 name 映 射为字符串类型。 我们说文档是无模式的,它们不需要拥有映射中所定义的所有字段,比如新增一个字段,那么 elasticsearch 是怎么做的呢?elasticsearch会自动的将新字段加入映射,但是这个字段的不确定它是什么类型,elasticsearch就开始猜,如果这个值是18,那么elasticsearch会认为它是整形。 但是elasticsearch也可能猜不对, 所以最安全的方式就是提前定义好所需要的映射,这点跟关系型数据库殊途同归了,先定义好字段,然后再使用。 索引 索引是映射类型的容器,elasticsearch 中的索引是一个非常大的文档集合。索引存储了映射类型的字段和其他设置。 然后它们被存储到了各个分片上了。 我们来研究下分片是如何工作的。物理设计 :节点和分片如何工作 一个集群至少有一个节点,而一个节点就是一个 elasricsearch 进程,节点可以有多个索引默认的,如果你创建索引,那么索引将会有个5个分片 ( primary shard ,又称主分片 ) 构成的,每一个主分片会有一个副本 ( replica shard ,又称复制分片 ) 下图是一个有3个节点的集群,可以看到主分片和对应的复制分片都不会在同一个节点内,这样有利于某个节点挂掉 了,数据也不至于丢失。 实际上,一个分片是一个 Lucene 索引,一个包含倒排索引的文件目录,倒排索引的结构使得elasticsearch在不扫描全部文档的情况下,就能告诉你哪些文档包含特定的关键字。 不过,等等,倒排索引是什么鬼?倒排索引 elasticsearch 使用的是一种称为倒排索引的结构,采用Lucene倒排索引作为底层。这种结构适用于快速的全文搜索, 一个索引由文档中所有不重复的列表构成,对于每一个词,都有一个包含它的文档列表。 例如,现在有两个文档, 每个文档包含如下内容:Study every day, good good up to forever # 文档1包含的内容

To forever, study every day, good good up # 文档2包含的内容

为了创建倒排索引,我们首先要将每个文档拆分成独立的词(或称为词条或者tokens),然后创建一个包含所有不重复的词条的排序列表,然后列出每个词条出现在哪个文档 : 现在,我们试图搜索 to forever,只需要查看包含每个词条的文档 两个文档都匹配,但是第一个文档比第二个匹配程度更高。如果没有别的条件,现在,这两个包含关键字的文档都将返回。 再来看一个示例,比如我们通过博客标签来搜索博客文章。那么倒排索引列表就是这样的一个结构 : 如果要搜索含有 python 标签的文章,那相对于查找所有原始数据而言,查找倒排索引后的数据将会快的多。只需要 查看标签这一栏,然后获取相关的文章ID即可。完全过滤掉无关的所有数据,提高效率! 在 elasticsearch 中, 索引这个词被频繁使用,这就是术语的使用。在 elasticsearch 中,索引被分为多个分片,每份分片是一个 Lucene 的索引。所以 一个 elasticsearch 索引是由多个Lucene索引组成的。别问为什么,谁让elasticsearch使用Lucene作为底层呢! 如无特指,说起索引都是指elasticsearch的索引。ES基础操作IK 分词器 什么是IK分词器? 分词:即把一段中文或者别的内容划分成一个个的关键字,我们在搜索时候会把自己的信息进行分词,是因为数据库中或者索引库中的数据也会进行分词,然后进行一个匹配操作,默认的中文分词是将每个字看成一个词,比如 “我爱大数据” 会被分为"我","爱","大", "数","据",这显然是不符合要求的,所以我们需要安装中文分词器 ik 来解决这个问题。 提前说一嘴,IK提供了两个分词算法:ik_smart 和 ik_max_word ,其中 ik_smart 为最少切分,ik_max_word 为 最细粒度划分!这个我们后面会来进行测试。安装步骤 1、下载ik分词器的包,Github地址:https://github.com/medcl/elasticsearch-analysis-ik/ (版本要对 应)。但目前我们es的版本是7.11,而现在发布的最新 ik 分词器的版本也才 7.10.2,那我们就先下载最新的版本 2. 然后直接在软件包的存储目录下,直接执行命令:[root@node01 software]# wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.10.2/elasticsearch-analysis-ik-7.10.2.zip

3. 解压下载好的压缩包,注意,解压路径必须放在 es 的 plugins 目录下[root@node01 software]# unzip elasticsearch-analysis-ik-7.10.2.zip -d ../servers/elasticsearch-7.11.0/plugins/ik

4. 给文件夹权限[root@node01 plugins]# chmod 777 ik

5. 正常情况下我们重启 Elasticsearch 即可看到插件加载的日志,但是很遗憾,终究因为版本不同的问题,导致 es 无法重启成功 所以关于分词器的部分就先停更,等到 ik 分词器出到 7.11 版本,再做更新???这是不可能的,所以我先用其他服务器上的一个 6.5.4 版本的 es 来做测试。 然后我们打开 6.5.4 版本的 kibana 界面,可以发现跟我们最新下载的7.11 版本的 kibana 界面还是区别还是挺大的! 但这并不影响我们接下来的操作,进入Dev Tools工具栏界面,先尝试用过 ik_smart 最少切分,发起一个 GET 请求GET _analyze

{

"analyzer":"ik_smart",

"text": "梦想家"

}

返回的结果如下: 那我们再用相同的文字测试一次ik_max_word 最细粒度划分:GET _analyze

{

"analyzer":"ik_max_word",

"text": "梦想家"

}

此时返回的结果: 此时,相信已经有聪明的小伙伴能得出下面的结论:ik_max_word 是细粒度分词,会穷尽一个语句中所有分词可能 ik_smart 是粗粒度分词,优先匹配最长词,不会有重复的数据 那大家有没有想过细粒度分词穷尽词库的可能,那词库是哪里的?一定是存在有类似"字典"这样的东西,不相信的话, 我们再用细粒度分词ik_max_word来做个测试GET _analyze

{

"analyzer":"ik_smart",

"text": "超级喜欢狂神说"

}

此时返回的结果: 可以发现此时狂神说几个字被拆开了,那如果我们想让系统识别“狂神说”是一个词,就需要我们编辑自定义词库。 步骤同样非常简单: (1) 进入elasticsearch/plugins/ik/config目录 (2) 新建一个my.dic文件,编辑内容:狂神说

(3) 修改IKAnalyzer.cfg.xml(在 ik/config 目录下)

IK Analyzer 扩展配置

my.dic

修改完配置重新启动 elasticsearch,再次测试! 此时可以发现,狂神说已经变成了一个词了~ 到了这里,我们就明白了分词器的基本规则和使用了!实际上搜索引擎做的最重要的一件事,就是分词!它需要将我们搜索的内容进行关键字的拆分,然后展示对应的信息。那这些被拆分出来的词是如何划分权重的呢?不用担心,马上我们就来开始学习 es 基本的增删改查!Rest风格说明 什么是 Rest 风格呢?一种软件架构风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。 其中 基本 的 Rest 命令说明:methodurl地址描述 那接下来我们就用之前已经安装好的 kibana 进行一个基础测试关于索引的基本操作基础测试 创建一个索引 PUT /索引名/类型名/文档id {请求id} 根据网址:ip:5601打开我们的 kibana 的页面,进入到开发工具栏,在 Console 中输入 :// 命令解释

// PUT 创建命令 test1 索引 type1 类型 1 id

PUT /test1/type1/1

{

"name":"大数据梦想家",

"age":21

}

如下图所示: 返回结果 (是以REST ful 风格返回的 ): 然后我们在elasticsearch-head中的数据浏览模块,就可以看见我们完成了自动创建索引,数据也成功添加进来了,所以建议初学时,可以将 es 当做是一个数据库来学习。 那么 name 这个字段用不用指定类型呢。毕竟我们关系型数据库 是需要指定类型的啊字段类型 elasticsearch 常见的字段类型如下:字符串类型text 、 keyword数值类型long, integer, short, byte, double, float, half_float, scaled_float日期类型date布尔值类型boolean二进制类型binary等等PUT新增 现在我们在kibana面板上新建一个索引并指定字段类型PUT /test2

{

"mappings": {

"properties": {

"name":{

"type":"text"

},

"age":{

"type":"long"

},

"birthday":{

"type":"date"

}

}

}

}

输出如下,说明创建成功了{

"acknowledged" : true,

"shards_acknowledged" : true,

"index" : "test2"

}

在elasticsearch-head上可以查看到我们目前还未添加任何数据 GET 查看 现在我们来尝试使用一下 GET 命令,请求具体的信息! 可以发现通过GET请求,我们能够详细获取到该索引下具体的信息,其中包含字段类型。那上面示例中字段类型是我自己定义的,那么我们不定义类型会是什么情况呢? 我们首先发起一个PUT请求,创建一个新的索引 test3,并添加一条数据PUT /test3/_doc/1

{

"name":"大数据梦想家",

"age":21,

"birthday":"2000-02-06"

}

然后通过GET请求,可以发现非常的智能。但是如果我们的文档字段类型没有指定,那么es就会给我们默认配置的字段类型! UPDATE修改 那如果我们想要修改文档里的字段信息呢?我们可以选择 UPDATE 也可以 选择 PUT进行覆盖 例如我可以像下图中的例子,将之前test3索引中的1号文档中的 name 字段修改后,重复提交,发现更新成功,但是注意 version 版本号已经变成了2 但是注意这种方法有弊端,如果我们在PUT的过程中,遗漏了字段,那么数据就会被新数据覆盖!所以,修改数据不建议使用PUT覆盖的方式! 我们使用 POST 命令,在 id 后面跟 _update ,要修改的内容放到 doc 文档(属性)中即可。 可以发现此时更新之后的version变成了3。所以,一旦索引被创建了之后,所有的修改都可以通过版本号看到变化。DELETE删除 那么怎么删除一条索引呢(库)呢?我们需要使用到DELETE命令 执行完成之后,到elasticsearch-head中查看索引,可以发现已经被删除了 结论: 通过 DELETE 命令实现删除,根据请求判断是删除索引还是删除文档记录!因此,使用 RESTFUL 风格是我们学习ES值得推荐使用的其他命令 我们可以通过GET _cat/health来获取集群的一个健康状态 同时观察elasticsearch-head,可以得出该界面实际上是在不断的像 elasticsearch 发起 GET 请求,然后将结果可视化展示在页面上! 除了看集群的健康信息,我们还可以看什么呢? 通过命令GET _cat/indices?v,我们可以获取到当前索引的很多信息,返回值包括所有索引的状态健康情况,分片,数据储存大小等等 关于文档的基本操作 接下来我们学习关于文档的基本操作,首先先重新创建一个新的索引,并添加一些数据PUT /alice/user/1

{

"name":"爱丽丝",

"age":21,

"desc":"在最美的年华,做最好的自己!",

"tags":["技术宅","温暖","思维活跃"]

}

PUT /alice/user/2

{

"name":"张三",

"age":23,

"desc":"法外狂徒",

"tags":["渣男","交友"]

}

PUT /alice/user/3

{

"name":"路人甲",

"age":24,

"desc":"不可描述",

"tags":["靓仔","网游"]

}

打开elasticsearch-head界面,确保我们的数据成功添加到了 es 接下来就可以进行文档的基本操作了!简单查询 通过 GET 命令,我们可以搜索到指定 id 的文档信息GET alice/user/1

当然这是简单的搜索,下面我们来看一下 es 如何做条件查询条件查询_search?q=

我们可以通过如下命令,来进行条件查询GET alice/user/_search?q=name:张三

我们看一下结果 返回并不是 数据本身,是给我们了一个 hits ,还有 _score得分,就是根据算法算出和查询条件匹配度高的分就越高。 我们在以某度为例的搜索引擎上进行搜索也是一样的道理,权重越高网站的位置就越靠前! 但我们一般使用不会直接加条件去查询,更多的会用到下面要介绍到的复杂操作搜索。复杂操作搜索 select( 排序,分页,高亮,模糊查询,精准查询!) 为了方便测试,我又执行下面的命令,往Alice索引下添加了2个文档PUT /alice/user/4

{

"name":"爱丽丝学Java",

"age":25,

"desc":"技术成就自我!",

"tags":["思维敏捷","喜欢学习"]

}

PUT /alice/user/5

{

"name":"爱丽丝学Python",

"age":26,

"desc":"人生苦短,我用Python!",

"tags":["好学","勤奋刻苦"]

}

刷新,查看到现在已经有了5条数据: 现在我们来构建一个查询:GET alice/user/_search

{

"query":{

"match": {

"name": "爱丽丝"

}

}

}

默认的话,es会查询出文档的所有字段,如果我们只想要部分的字段,就可以像下面所展示的demo进行查询:GET alice/user/_search

{

"query":{

"match": {

"name": "爱丽丝"

}

},

"_source":["name","desc"]

}

如上例所示,在查询中,通过 _source 来控制仅返回 name 和 desc 属性。页面返回的查询结果如下: 一般的,我们推荐使用构建查询,以后在与程序交互时的查询等也是使用构建查询方式处理查询条件,因为该方式可以构建更加复杂的查询条件,也更加一目了然。排序查询 我们说到排序,有人就会想到:正序或倒序。那么我们先来根据age字段倒序查询:GET alice/user/_search

{

"query":{

"match": {

"name": "爱丽丝"

}

},

"sort": [

{

"age":

{

"order": "desc"

}

}

]

}

查询返回的结果如下: 同理,如果我们想要正序查询,只需要将desc换成了asc即可。GET alice/user/_search

{

"query":{

"match": {

"name": "爱丽丝"

}

},

"sort": [

{

"age":

{

"order": "asc"

}

}

],

"from":0,

"size":1

}

查询结果如下: 注意:在排序的过程中,只能使用可排序的属性进行排序。那么可以排序的属性有哪些呢?数字日期ID其他都不行!分页查询 学到这里,我们也可以看到,我们的查询条件越来越多,开始仅是简单查询,慢慢增加条件查询,增加排序,对返回结果进行限制。所以,我们可以说,对 于 elasticsearch 来说,所有的查询条件都是可插拔的。比如说,我们在查询中,仅对返回结果进行限制:GET alice/user/_search

{

"query":

{"match_all": {}

},

"from":0, # 从第n条开始

"size":4 # 返回n条数据

}

分页查询类似于我们SQL中的 limit 语句。在 es 中我们想要实现这样的效果只需要用 from 指定 从第几条数据开始,size指定返回多少条数据即可。 布尔查询must (and) 我们上面已经讲过了通过构建查询的方法去做模糊查询,那我们如果想多条件查询,例如查询name为alice,并且age是25岁,那该如何查询呢? 我们通过在 bool属性内使用 must 来作为查询条件!看结果,是不是 有点像and的感觉,里面的条件需要都满足!GET alice/user/_search

{

"query":{

"bool": {

"must":[

{

"match":{

"name":"爱丽丝"

}

},

{

"match":{

"age":25

}

}

]

}

}

}

查询结果如下 should (or) 那么我要查询name为爱丽丝或 age 为 25 的呢? 我们只需要将boolean属性内的must值换成should 即可,这就有点相当于 or 的感觉GET alice/user/_search

{

"query":{

"bool": {

"should":[

{

"match":{

"name":"爱丽丝"

}

},

{

"match":{

"age":25

}

}

]

}

}

}

查询结果如下must_not (not) 那现在我想要查询年龄不是 25 的 数据,只需要将boolean的属性值换成must_not即可GET alice/user/_search

{

"query":{

"bool": {

"must_not":[

{

"match":{

"age":25

}

}

]

}

}

}

查询结果如下: Fitter 那如果查询 name 为爱丽丝,age 大于 24 的数据,需要使用到filter进行过滤。GET alice/user/_search

{

"query":{

"bool":{

"must": [

{

"match": {

"name": "爱丽丝"

}

}

],

"filter": [

{

"range": {

"age": {

"gt": 24

}

}

}

]

}

}

}

查询结果如下,可以发现只有age为25 和 26的两条数据 这里就用到了 filter 条件过滤查询,过滤条件的范围用 range 表示,其余操作如下 :gt 表示大于gte 表示大于等于lt 表示小于lte 表示小于等于 那现在要查询,例如 age 在24到26之间的数据该如何查询?GET alice/user/_search

{

"query":{

"bool":{

"filter": [

{

"range": {

"age": {

"gte": 24,

"lte": 26

}

}

}

]

}

}

}

查询结果: 短语检索 为了方便测试,我们再加入几条文档数据:PUT /alice/user/6

{

"name":"大数据老K",

"age":25,

"desc":"技术成就自我!",

"tags":["男","学习","技术"]

}

PUT /alice/user/7

{

"name":"Python女侠",

"age":26,

"desc":"人生苦短,我用Python!",

"tags":["靓女","勤奋学习","善于交际"]

}

例如现在需要查询tags中包含“男”的数据GET alice/user/_search

{

"query":{

"match":{

"tags":"男"

}

}

}

查询结果如下:匹配多个标签 既然按照标签检索,那么,能不能写多个标签呢?GET alice/user/_search

{

"query":{

"match":{

"tags":"男 学习"

}

}

}

此时我们可以观察返回的结果,可以发现只要满足一个标签就能返回这个数据了精确查询term查询是直接通过倒排索引指定的词条进程精确查找的!关于分词:term ,不经过分词,直接查询精确的值match,会使用分词器解析!(先分析文档,然后再通过分析的文档进行查询!) 说到分词器解析,就不得不提到两种数据类型:text和keyword。下面我们就来做个测试:// 创建一个索引,并指定类型

PUT testdb

{

"mappings": {

"properties": {

"name":{

"type": "text"

},

"desc":{

"type":"keyword"

}

}

}

}

// 插入数据

PUT testdb/_doc/1

{

"name":"爱丽丝学大数据name",

"desc":"爱丽丝学大数据desc"

}

PUT testdb/_doc/2

{

"name":"爱丽丝学大数据name2",

"desc":"爱丽丝学大数据desc2"

}

上述中testdb索引中,字段name在被查询时会被分析器进行分析后匹配查询。而属于keyword类型不会被分析器处理。 我们来验证一下:GET _analyze

{

"analyzer": "keyword",

"text": "爱丽丝学大数据 name"

}

查询结果: 是不是没有被分析~就是简单的一个字符串啊。再测试一下:GET _analyze

{

"analyzer": "standard",

"text": "爱丽丝学大数据 name"

}

查询结果: 然后我们可以得出结论:keyword 字段类型不会被分析器分析! 下面我们用前面添加的2条数据做过测试: 先精准查询text类型的字段GET testdb/_search // text 会被分析器分析 查询

{

"query": {

"term": {

"name": "爱"

}

}

}

查询结果,2条数据都能匹配到 然后用standard类型做精准测试GET testdb/_search // keyword 不会被分析所以直接查询

{

"query": {

"term": {

"desc": "爱丽丝学大数据desc"

}

}

}

查询结果,只有1条数据能匹配到 查找多个精确值 为了方便测试,我们再添加如下数据:PUT testdb/_doc/3

{

"t1":"22",

"t2":"2021-03-01"

}

PUT testdb/_doc/4

{

"t1":"33",

"t2":"2021-03-01"

}

然后进行查询GET testdb/_search

{

"query": {

"bool":{

"should": [

{

"term": {

"t1":"22"

}

},

{

"term": {

"t1":"33"

}

}

]

}

}

}

查询结果: 可以发现2条数据也都能查到,证明就算是term精确查询,也能够查询多个值。 当然,除了 bool 查询之外,下面这种方式也同样是可以的。GET testdb/_doc/_search

{

"query":{

"terms":{

"t1":["22","33"]

}

}

}

下面要介绍的功能,就是经常被搜索引擎用到的“高亮显示”!高亮显示 我们可以通过highlight属性,来对我们查询的结果的指定字段做高亮显示!GET alice/user/_search

{

"query":{

"match": {

"name": "爱丽丝"

}

},

"highlight":{

"fields": {

"name": {}

}

}

}

观察返回的结果,我们可以发现搜索相关的结果,被加上了高亮标签 现在效果看到了,那我们有没有办法自定义样式呢? 答案当然是可以的,我们需要在pre_tags中定义标签的前缀,post_tags中定义后缀!GET alice/user/_search

{

"query":{

"match": {

"name": "爱丽丝"

}

},

"highlight":{

"pre_tags": "",

"post_tags": "",

"fields": {

"name": {}

}

}

}

查询结果: 好了,学到这里,关于elasticsearch 文档的基本操作基本就演示完了。我们来回顾下:简单匹配条件匹配精确匹配区间范围匹配匹配字段过滤多条件查询高亮查询 值得一提的是,这些MySQL也都能做,只是效率较低!小结 看到这里,写了好几天的 elasticsearch 的入门级教程也算是先告一段落了。对于初学者来说,认真阅读并理解,看完之后,elasticsearch 入个门是没问题的,但是如果能在实际的应用场景中,将其运用起来,相信大家能有更好的理解!因为我是大数据方向的,后续我可能会出关于 elasticsearch 的实战教程 ,敬请期待!喜欢的话记得一键三连,持续关注哟~巨人的肩膀https://www.cnblogs.com/jizhong/p/12102100.htmlhttps://www.cnblogs.com/subendong/p/7667558.htmlhttps://blog.csdn.net/Bobdragery/article/details/106842984https://blog.csdn.net/u014475245/article/details/107184892/https://www.bilibili.com/video/BV17a4y1x7zq?p=7&spm_id_from=pageDriver编辑于 2021-04-24 18:46全文检索ElasticsearchSolr​赞同 154​​11 条评论​分享​喜欢​收藏​申请转载​文章被以下专栏收录大数据技术包含Hadoop技术圈常用的技术或周边

ElasticSearch入门篇(保姆级教程) - coderxz - 博客园

ElasticSearch入门篇(保姆级教程) - coderxz - 博客园

会员

周边

新闻

博问

AI培训

云市场

所有博客

当前博客

我的博客

我的园子

账号设置

简洁模式 ...

退出登录

注册

登录

coderxz

博客园

首页

新随笔

联系

订阅

管理

ElasticSearch入门篇(保姆级教程)

本章将介绍:ElasticSearch的作用,搭建elasticsearch的环境(Windows/Linux),ElasticSearch集群的搭建,可视化客户端插件elasticsearch-head的安装及使用,对IK分词器的安装及使用;本章介绍的ElasticSearch操作基于Restful形式(使用http请求的形式),java代码操作请参考下篇

本章将介绍:ElasticSearch的作用,搭建elasticsearch的环境(Windows/Linux),ElasticSearch集群的搭建,可视化客户端插件elasticsearch-head的安装及使用,对IK分词器的安装及使用;本章介绍的ElasticSearch操作基于Restful形式(使用http请求的形式),java代码操作请参考下篇

@目录1.ElasticSearch简介1.1ElasticSearch的使用案例1.2 ElasticSearch与solr的对比2.1 安装2.2修改配置文件2.3 启动2.4 安装图形化插件3.ES相关概念3.1 概述(重要)3.2 核心概念1)index索引-2)type类型3)Filed字段4)映射mapping5)document文档6)集群cluster7)节点node8)分片和复制 shards&replicas4.ElasticSearch客户端操作4.1使用Restful接口直接访问4.2使用Talend API tester进行es客户端操作。1)Elasticsearch的接口语法2)创建索引库index并添加映射mapping------PUT3)先创建索引index,再添加mapping ----PUT4)删除索引index ----DELETE5)创建文档document(向索引库中添加内容)---POST6)修改document内容----POST7)删除文档document---DELETE8)查询文档document-----GETi.根据id查询ii.根据关键字查询-term查询iii.查询文档-querystring查询4.3使用elasticsearch-head进行es客户端操作5.IK分词器和Elasticsearch集成使用5.1IK分词器的安装5.2IK分词器测试6.ElasticSearch集群6.1 集群的搭建(Windows)1)准备三台elasticsearch服务器:2)修改每台服务器的配置3.启动各个节点服务器4.集群测试7.ElasticSearch安装(Linux)1)保证你已经安装了java环境2)修改配置文件3)启动4)配置外网访问9200端口 需要开放服务器的端口5)后台启动

1.ElasticSearch简介

Elaticsearch,简称为es, es是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的存储、检索数据;本

身扩展性很好,可以扩展到上百台服务器,处理PB级别的数据。es也使用Java开发并使用Lucene作为其核心来实

现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得

简单。

1.1ElasticSearch的使用案例

2013年初,GitHub抛弃了Solr,采取ElasticSearch 来做PB级的搜索。 “GitHub使用ElasticSearch搜索20TB

的数据,包括13亿文件和1300亿行代码”

维基百科:启动以elasticsearch为基础的核心搜索架构

SoundCloud:“SoundCloud使用ElasticSearch为1.8亿用户提供即时而精准的音乐搜索服务”

百度:百度目前广泛使用ElasticSearch作为文本数据分析,采集百度所有服务器上的各类指标数据及用户自定义数据,通过对各种数据进行多维分析展示,辅助定位分析实例异常或业务层面异常。目前覆盖百度内部20多个业务线(包括casio、云分析、网盟、预测、文库、直达号、钱包、风控等),单集群最大100台机器,200个ES节点,每天导入30TB+数据

新浪使用ES 分析处理32亿条实时日志

阿里使用ES 构建挖财自己的日志采集和分析体系

1.2 ElasticSearch与solr的对比

Solr 利用 Zookeeper 进行分布式管理,而 Elasticsearch 自身带有分布式协调管理功能;

Solr 支持更多格式的数据,而 Elasticsearch 仅支持json文件格式;

Solr 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提供;

Solr 在传统的搜索应用中表现好于 Elasticsearch,但在处理实时搜索应用时效率明显低于 Elasticsearch

2.ElasticSearch安装(windows)

下载压缩包:

ElasticSearch的官方地址: https://www.elastic.co/products/elasticsearch

2.1 安装

注意:es使用java开发,使用lucene作为核心,需要配置好java环境!(jdk1.8以上)

类似与tomcat,直接解压即可。其目录结构如下:

2.2修改配置文件

修改conf\jvm.option文件

将#-Xms2g

#-Xmx2g修改成为:

-Xms340m

-Xmx340m

否则因为虚拟机内存不够无法启动

修改conf\elasticsearch.yml文件

elasticsearch-5.6.8\config\elasticsearch.yml中末尾加入:

http.cors.enabled: true

http.cors.allow-origin: "*"

network.host: 127.0.0.1

目的是使ES支持跨域请求

2.3 启动

点击ElasticSearch下的bin目录下的elasticsearch.bat启动,控制台显示的日志信息如下:

注意:9300是tcp通信端口,es集群之间使用tcp进行通信,9200是http协议端口。

我们在浏览器可以访问:

2.4 安装图形化插件

上述可以发现,ElasticSearch不同于Solr自带图形化界面,我们可以通过安装ElasticSearch的head插件,完成图形化界面的效果,完成索引数据的查看。安装插件的方式有两种,在线安装和本地安装。本文档采用本地安装方式进行head插件的安装。elasticsearch-5-*以上版本安装head需要安装node和grunt 。

下载head插件:https://github.com/mobz/elasticsearch-head

下载压缩包后解压即可。

下载node.js:https://nodejs.org/en/download/

双击安装,通过cmd输入 node -v查看版本号

将grunt安装为全局命令 ,Grunt是基于Node.js的项目构建工具

在cmd中输入:

npm install ‐g grunt‐cli

由于访问的是国外的服务器,如果下载速度较慢,可以切换淘宝镜像

npm install -g cnpm –registry=https://registry.npm.taobao.org

后续使用的时候,只需要把npm xxx 换成 cnpm xxx 即可

检测是否安装成功

npm config get registry

注意:后续使用时需要将npm替换为cnpm。

启动head

进入head插件目录,打开cmd,输入:

>npm install

>grunt server

打开浏览器,输入http://localhost:9100即可

3.ES相关概念

3.1 概述(重要)

Elasticsearch是面向文档(document oriented)的,这意味着它可以存储整个对象或文档(document)。然而它不仅

仅是存储,还会索引(index)每个文档的内容使之可以被搜索。在Elasticsearch中,你可以对文档(而非成行成列的数据)进行索引、搜索、排序、过滤。Elasticsearch比传统关系型数据库如下:

Relational DB ‐> Databases ‐> Tables ‐> Rows ‐> Columns

Elasticsearch ‐> Indices ‐> Types ‐> Documents ‐> Fields

3.2 核心概念

1)index索引-

一个索引就是一个拥有几分相似特征的文档的集合。比如说,你可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单数据的索引。一个索引由一个名字来标识(必须全部是小写字母的),并且当我们要对对应于这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。在一个集群中,可以定义任意多的索引。可类比mysql中的数据库

2)type类型

在一个索引中,你可以定义一种或多种类型。一个类型是你的索引的一个逻辑上的分类/分区,其语义完全由你来定。通常,会为具有一组共同字段的文档定义一个类型。比如说,我们假设你运营一个博客平台并且将你所有的数据存储到一个索引中。在这个索引中,你可以为用户数据定义一个类型,为博客数据定义另一个类型,当然,也可以为评论数据定义另一个类型。 可类比mysql中的表

3)Filed字段

相当于是数据表的字段,对文档数据根据不同属性进行的分类标识 。

4)映射mapping

mapping是处理数据的方式和规则方面做一些限制,如某个字段的数据类型、默认值、分析器、是否被索引等等,这些都是映射里面可以设置的,其它就是处理es里面数据的一些使用规则设置也叫做映射,按着最优规则处理数据对性能提高很大,因此才需要建立映射,并且需要思考如何建立映射才能对性能更好。相当于mysql中的创建表的过程,设置主键外键等等

5)document文档

一个文档是一个可被索引的基础信息单元。比如,你可以拥有某一个客户的文档,某一个产品的一个文档,当然,也可以拥有某个订单的一个文档。文档以JSON(Javascript Object Notation)格式来表示,而JSON是一个到处存在的互联网数据交互格式。在一个index/type里面,你可以存储任意多的文档。注意,尽管一个文档,物理上存在于一个索引之中,文档必须被索引/赋予一个索引的type。 插入索引库以文档为单位,类比与数据库中的一行数据

6)集群cluster

一个集群就是由一个或多个节点组织在一起,它们共同持有整个的数据,并一起提供索引和搜索功能。一个集群由 一个唯一的名字标识,这个名字默认就是“elasticsearch”。这个名字是重要的,因为一个节点只能通过指定某个集 群的名字,来加入这个集群。

7)节点node

一个节点是集群中的一个服务器,作为集群的一部分,它存储数据,参与集群的索引和搜索功能。和集群类似,一 个节点也是由一个名字来标识的,默认情况下,这个名字是一个随机的漫威漫画角色的名字,这个名字会在启动的 时候赋予节点。这个名字对于管理工作来说挺重要的,因为在这个管理过程中,你会去确定网络中的哪些服务器对 应于Elasticsearch集群中的哪些节点。

一个节点可以通过配置集群名称的方式来加入一个指定的集群。默认情况下,每个节点都会被安排加入到一个叫 做“elasticsearch”的集群中,这意味着,如果你在你的网络中启动了若干个节点,并假定它们能够相互发现彼此, 它们将会自动地形成并加入到一个叫做“elasticsearch”的集群中。

在一个集群里,只要你想,可以拥有任意多个节点。而且,如果当前你的网络中没有运行任何Elasticsearch节点, 这时启动一个节点,会默认创建并加入一个叫做“elasticsearch”的集群。

8)分片和复制 shards&replicas

一个索引可以存储超出单个结点硬件限制的大量数据。比如,一个具有10亿文档的索引占据1TB的磁盘空间,而任一节点都没有这样大的磁盘空间;或者单个节点处理搜索请求,响应太慢。为了解决这个问题,Elasticsearch提供了将索引划分成多份的能力,这些份就叫做分片。当你创建一个索引的时候,你可以指定你想要的分片的数量。每个分片本身也是一个功能完善并且独立的“索引”,这个“索引”可以被放置到集群中的任何节点上。分片很重要,主要有两方面的原因: 1)允许你水平分割/扩展你的内容容量。 2)允许你在分片(潜在地,位于多个节点上)之上进行分布式的、并行的操作,进而提高性能/吞吐量。

至于一个分片怎样分布,它的文档怎样聚合回搜索请求,是完全由Elasticsearch管理的,对于作为用户的你来说,这些都是透明的。

在一个网络/云的环境里,失败随时都可能发生,在某个分片/节点不知怎么的就处于离线状态,或者由于任何原因消失了,这种情况下,有一个故障转移机制是非常有用并且是强烈推荐的。为此目的,Elasticsearch允许你创建分片的一份或多份拷贝,这些拷贝叫做复制分片,或者直接叫复制。

复制之所以重要,有两个主要原因: 在分片/节点失败的情况下,提供了高可用性。因为这个原因,注意到复制分片从不与原/主要(original/primary)分片置于同一节点上是非常重要的。扩展你的搜索量/吞吐量,因为搜索可以在所有的复制上并行运行。总之,每个索引可以被分成多个分片。一个索引也可以被复制0次(意思是没有复制)或多次。一旦复制了,每个索引就有了主分片(作为复制源的原来的分片)和复制分片(主分片的拷贝)之别。分片和复制的数量可以在索引创建的时候指定。在索引创建之后,你可以在任何时候动态地改变复制的数量,但是你事后不能改变分片的数量。

默认情况下,Elasticsearch中的每个索引被分片5个主分片和1个复制,这意味着,如果你的集群中至少有两个节点,你的索引将会有5个主分片和另外5个复制分片(1个完全拷贝),这样的话每个索引总共就有10个分片。

4.ElasticSearch客户端操作

上述部分为理论部分,实际开发中,主要有三种方式可以作为es服务的客户端:

使用elasticsearch-head插件

使用elasticsearch提供的Restful接口直接访问

使用elasticsearch提供的API进行访问

4.1使用Restful接口直接访问

我们需要使用http请求,介绍两款接口测试工具:postman和Talend API tester。

Talend API tester安装:

这是一款chrome插件,无需下载;

Postman安装:

Postman官网:https://www.getpostman.com

4.2使用Talend API tester进行es客户端操作。

1)Elasticsearch的接口语法

curl ‐X '://:/?' ‐d ''

其中:

2)创建索引库index并添加映射mapping------PUT

PUT

请求体:

article:type类型;相当于这个索引库中有张表叫做article下面定义的这张表中的字段的定义,

字段默认为不索引的;

analyzer:分词器使用标准分词器

{

"mappings": {

"article": {

"properties": {

"id": {

"type": "long",

"store": true,

"index": "not_analyzed"

},

"title": {

"type": "text",

"store": true,

"index": "analyzed",

"analyzer": "standard"

},

"content": {

"type": "text",

"store": true,

"index": "analyzed",

"analyzer": "standard"

}

}

}

}

}

在可视化工具elasticsearch-head中查看:

3)先创建索引index,再添加mapping ----PUT

我们可以在创建索引时设置mapping信息,当然也可以先创建索引然后再设置mapping。

在上一个步骤中不设置maping信息,直接使用put方法创建一个索引,然后设置mapping信息。

请求的url:

PUT http://127.0.0.1:9200/hello2/article/_mapping

请求体:

{

"article": {

"properties": {

"id": {

"type": "long",

"store": true,

"index": "not_analyzed"

},

"title": {

"type": "text",

"store": true,

"index": "analyzed",

"analyzer": "standard"

},

"content": {

"type": "text",

"store": true,

"index": "analyzed",

"analyzer": "standard"

}

}

}

}

4)删除索引index ----DELETE

请求URL:

DELETE http://127.0.0.1:9200/hello2

5)创建文档document(向索引库中添加内容)---POST

请求URL:

POST http://127.0.0.1:9200/hello/article/1

请求体:

{

"id": 1,

"title": "ElasticSearch是一个基于Lucene的搜索服务器",

"content": "它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。"

}

在elasticsearch-head中查看:

注意,一般我们将_id与id赋相同值。

6)修改document内容----POST

请求URL:

POST http://127.0.0.1:9200/hello/article/1

在elasticsearch-head中查看:

7)删除文档document---DELETE

请求URL:

DELETE http://127.0.0.1:9200/hello/article/2

8)查询文档document-----GET

查询文档有三种方式:

根据id查询;

根据关键词查询

根据输入的内容先分词,再查询

i.根据id查询

请求URL:

GET http://127.0.0.1:9200/hello/article/1

ii.根据关键字查询-term查询

请求URL:

POST http://127.0.0.1:9200/hello/article/_search

请求体:

{

"query": {

"term": {

"title": "搜"

}

}

}

iii.查询文档-querystring查询

请求URL:

POST http://127.0.0.1:9200/hello/article/_search

请求体:

{

"query": {

"query_string": {

"default_field": "title",

"query": "搜索服务器"

}

}

}

指定:

在哪个字段上进行查询;

要查询的内容是什么;

它会把查询内容先进行分词,再进行查询

4.3使用elasticsearch-head进行es客户端操作

在elasticsearch-head中集成了http请求的工具,可以提供复查查询:

5.IK分词器和Elasticsearch集成使用

上述分词器使用的是标准分词器,其对中文分词不是很友好,例如对我是程序员进行分词得到:

GET http://127.0.0.1:9200/_analyze?analyzer=standard&pretty=true&text=我是程序员

"tokens":[

{"token": "我", "start_offset": 0, "end_offset": 1, "type": "",…},

{"token": "是", "start_offset": 1, "end_offset": 2, "type": "",…},

{"token": "程", "start_offset": 2, "end_offset": 3, "type": "",…},

{"token": "序", "start_offset": 3, "end_offset": 4, "type": "",…},

{"token": "员", "start_offset": 4, "end_offset": 5, "type": "",…}

]

我们希望达到的分词是:我、是、程序、程序员。

支持中文的分词器有很多,word分词器,庖丁解牛,Ansj分词器,下面注意说IK分词器的使用。

5.1IK分词器的安装

1)下载地址:https://github.com/medcl/elasticsearch-analysis-ik/releases

2)解压,将解压后的elasticsearch文件夹拷贝到elasticsearch-5.6.8\plugins下,并重命名文件夹为analysis-ik (其他名字也可以,目的是不要重名)

3)重新启动ElasticSearch,即可加载IK分词器

5.2IK分词器测试

IK提供两种分词ik_smart和ik_max_word

其中ik_smart为最少切分,ik_max_word为最细粒度划分。

下面测试一下:

最小切分:在浏览器输入地址:

GET http://127.0.0.1:9200/_analyze?analyzer=ik_smart&pretty=true&text=我是程序员

返回结果:

"tokens":[

{"token": "我", "start_offset": 0, "end_offset": 1, "type": "CN_CHAR",…},

{"token": "是", "start_offset": 1, "end_offset": 2, "type": "CN_CHAR",…},

{"token": "程序员", "start_offset": 2, "end_offset": 5, "type": "CN_WORD",…}

]

最新切分:在浏览器输入地址:

GET http://127.0.0.1:9200/_analyze?analyzer=ik_max_word&pretty=true&text=我是程序员

返回结果:

"tokens":[

{"token": "我", "start_offset": 0, "end_offset": 1, "type": "CN_CHAR",…},

{"token": "是", "start_offset": 1, "end_offset": 2, "type": "CN_CHAR",…},

{"token": "程序员", "start_offset": 2, "end_offset": 5, "type": "CN_WORD",…},

{"token": "程序", "start_offset": 2, "end_offset": 4, "type": "CN_WORD",…},

{"token": "员", "start_offset": 4, "end_offset": 5, "type": "CN_CHAR",…}

]

6.ElasticSearch集群

ES集群是一个 P2P类型(使用 gossip 协议)的分布式系统,除了集群状态管理以外,其他所有的请求都可以发送到集群内任意一台节点上,这个节点可以自己找到需要转发给哪些节点,并且直接跟这些节点通信。所以,从网络架构及服务配置上来说,构建集群所需要的配置极其简单。在 Elasticsearch 2.0 之前,无阻碍的网络下,所有配置了相同 cluster.name 的节点都自动归属到一个集群中。2.0 版本之后,基于安全的考虑避免开发环境过于随便造成的麻烦,从 2.0 版本开始,默认的自动发现方式改为了单播(unicast)方式。配置里提供几台节点的地址,ES 将其视作gossip router 角色,借以完成集群的发现。由于这只是 ES 内一个很小的功能,所以 gossip router 角色并不需要单独配置,每个 ES 节点都可以担任。所以,采用单播方式的集群,各节点都配置相同的几个节点列表作为 router即可。

集群中节点数量没有限制,一般大于等于2个节点就可以看做是集群了。一般处于高性能及高可用方面来

虑一般集群中的节点数量都是3个及3个以上 .

6.1 集群的搭建(Windows)

1)准备三台elasticsearch服务器:

2)修改每台服务器的配置

修改\comf\elasticsearch.yml配置文件:

#Node节点1:

http.cors.enabled: true

http.cors.allow-origin: "*"

#节点1的配置信息:

#集群名称,保证唯一

cluster.name: my-elasticsearch

#节点名称,必须不一样

node.name: node-1

#必须为本机的ip地址

network.host: 127.0.0.1

#服务端口号,在同一机器下必须不一样

http.port: 9201

#集群间通信端口号,在同一机器下必须不一样

transport.tcp.port: 9301

#设置集群自动发现机器ip集合

discovery.zen.ping.unicast.hosts: ["127.0.0.1:9301","127.0.0.1:9302","127.0.0.1:9303"]

#Node节点2:

http.cors.enabled: true

http.cors.allow-origin: "*"

#节点1的配置信息:

#集群名称,保证唯一

cluster.name: my-elasticsearch

#节点名称,必须不一样

node.name: node-2

#必须为本机的ip地址

network.host: 127.0.0.1

#服务端口号,在同一机器下必须不一样

http.port: 9202

#集群间通信端口号,在同一机器下必须不一样

transport.tcp.port: 9302

#设置集群自动发现机器ip集合

discovery.zen.ping.unicast.hosts: ["127.0.0.1:9301","127.0.0.1:9302","127.0.0.1:9303"]

#Node节点3:

http.cors.enabled: true

http.cors.allow-origin: "*"

#节点1的配置信息:

#集群名称,保证唯一

cluster.name: my-elasticsearch

#节点名称,必须不一样

node.name: node-3

#必须为本机的ip地址

network.host: 127.0.0.1

#服务端口号,在同一机器下必须不一样

http.port: 9203

#集群间通信端口号,在同一机器下必须不一样

transport.tcp.port: 9303

#设置集群自动发现机器ip集合

discovery.zen.ping.unicast.hosts: ["127.0.0.1:9301","127.0.0.1:9302","127.0.0.1:9303"]

3.启动各个节点服务器

可以分别启动每个服务器下的elasticsearch.bat,我这里使用的是windows下的批处理文件:

新建一个elasticsearch_cluster_start.bat文件,然后添加下面内容:

格式为:start "需要启动的文件名" "文件的路径" &表示启动A后继续执行。

start "elasticsearch.bat" "F:\Soft\ES-cluster\cluster01\bin\elasticsearch.bat" &

start "elasticsearch.bat" "F:\Soft\ES-cluster\cluster02\bin\elasticsearch.bat" &

start "elasticsearch.bat" "F:\Soft\ES-cluster\cluster03\bin\elasticsearch.bat"

关于Windows的批处理在本章就不细说了。

4.集群测试

只要连接集群中的任意节点,其操作方式与单机版本基本相同,改变的仅仅是存储的结构。

添加索引和映射

PUT http://127.0.0.1:9201/hello

请求体:

{

"mappings": {

"article": {

"properties": {

"id": {

"type": "long",

"store": true,

"index": "not_analyzed"

},

"title": {

"type": "text",

"store": true,

"index": true,

"analyzer": "ik_smart"

},

"content": {

"type": "text",

"store": true,

"index": true,

"analyzer": "ik_smart"

}

}

}

}

}

返回结果:

{

"acknowledged": true,

"shards_acknowledged": true,

"index": "hello"

}

添加文档

POST http://127.0.0.1:9201/hello/article/1

请求体:

{

"id":1,

"title":"ElasticSearch是一个基于Lucene的搜索服务器",

"content":"它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。"

}

返回值:

{

"_index": "hello",

"_type": "article",

"_id": "1",

"_version": 1,

"result": "created",

"_shards":{

"total": 2,

"successful": 2,

"failed": 0

},

"created": true

}

在elasticsearch-head中查看:

7.ElasticSearch安装(Linux)

1)保证你已经安装了java环境

可以直接把windows中的copy过去,不用安装,解压即可。

tar -zxf elasticsearch-6.3.2.tar.gz

2)修改配置文件

修改conf\jvm.option文件

将#-Xms2g

#-Xmx2g修改成为:

-Xms340m

-Xmx340m

否则因为虚拟机内存不够无法启动

修改conf\elasticsearch.yml文件

#elasticsearch-5.6.8\config\elasticsearch.yml中末尾加入:

http.cors.enabled: true

http.cors.allow-origin: "*"

network.host: 127.0.0.1

目的是使ES支持跨域请求

3)启动

注意:在linux环境下不支持root用户直接启动(理由是安全问题)

添加用户:

[root@coderxz bin]# useradd rxz -p rongxianzhao

[root@coderxz bin]# chown -R rxz:rxz /usr/local/elasticsearch/*

[root@coderxz bin]# su rxz

执行:

#注意:切换为非root用户执行哦

[rxz@coderxz bin]$ ./elasticsearch

查看运行状态:

检测是否运行:jps (显示所有的Java进程pid的命令)

ps aux|grep elasticsearch

[root@coderxz ~]# curl -X GET 'http://localhost:9200'

4)配置外网访问9200端口 需要开放服务器的端口

修改配置文件 config/elasticsearch.yml

network.host: 0.0.0.0

5)后台启动

如果你在服务器上安装Elasticsearch,而你想在本地机器上进行开发,这时候,你很可能需要在关闭终端的时候,让Elasticsearch继续保持运行。最简单的方法就是使用nohup。先按Ctrl + C,停止当前运行的Elasticsearch,改用下面的命令运行Elasticsearch。

nohup ./bin/elasticsearch&

posted @

2020-07-08 18:14 

coderxz 

阅读(120205) 

评论(12) 

编辑 

收藏 

举报

会员力量,点亮园子希望

刷新页面返回顶部

公告

Copyright © 2024 coderxz

Powered by .NET 8.0 on Kubernetes

Elasticsearch 入门 | Elasticsearch 中文文档

Elasticsearch 入门 | Elasticsearch 中文文档

Skip to main contentElasticsearch 中文文档BookHub 首页中文文档Elasticsearch 翻译说明什么是 Elasticsearch?Elasticsearch 入门启动并运行 Elasticsearch索引一些文档开始搜索使用聚合分析结果何去何从设置 Elasticsearch索引模块REST APIElasticsearch 入门Elasticsearch 入门准备试用 Elasticsearch,并且看看你怎么用 REST API 去存储、搜索和分析数据?通过本入门教程,可以:启动并运行 Elasticsearch 集群索引一些示例文档使用 Elasticsearch 查询语言搜索文档使用桶(bucket)和指标(metrics)聚合来分析结果需要更多的背景吗?查看Elasticsearch 简介 以学习术语,并理解 Elasticsearch运行的基本原理。如果你已熟悉 Elasticsearch,并且想要了解它如何与栈(Elastic Stack)的其他部分一起运行,那你可能希望跳到Elastic Stack 教程 去了解如何使用 Elasticsearch、Kibana、Beats和Logstash 去设置系统监控方案。注意最快的入门 Elasticsearch 的方法是在云中免费试用14天 Elasticsearch 服务。原文链接Previous可伸缩性和弹性:集群、节点和分片Next启动并运行 ElasticsearchBookHub首页中文文档其他文档MicronautMySQLPac4j更多计算机书库Copyright © 2024 bookHub.tech

Elasticsearch: The Official Distributed Search & Analytics Engine | Elastic

ticsearch: The Official Distributed Search & Analytics Engine | ElasticSkip to main contentPlatformPlatformSolutionsSolutionsCustomersCustomersResourcesResourcesPricingPricingDocsDocsLanguage pickerDeutschEnglishEspañolFrançais日本語한국어简体中文PortuguêsSearchLoginStart free trialContact SalesElasticsearch PlatformObservability, security, and search solutions — powered by the Elasticsearch Platform.Elastic overviewELK StackSearch and analytics, data ingestion, and visualization – all at your fingertipsKibanaElasticsearchIntegrationsELK Stack overviewElastic CloudFind answers that matter with Elastic on your preferred cloud provider.Cloud overviewPartnersContact salesJoin our serverless previewObservabilityUnify app and infrastructure visibility to proactively resolve issues.Log monitoringApplication performance monitoringInfrastructure monitoringSynthetic monitoringReal user monitoringUniversal profilingAIOpsOpenTelemetryObservability overviewSecurityProtect, investigate, and respond to cyber threats quickly and at scale.Continuous monitoringThreat huntingInvestigation and incident responseAutomated threat protectionSecurity overviewSearchAccelerate search results across any cloud and increase personalization.Generative AISearch applicationsEcommerceWebsiteWorkplace searchCustomer supportSearch overviewBy industryPublic sectorFinancial servicesTelecommunicationsHealthcareTechnologyRetail and EcommerceManufacturing and automotiveView all industriesBy solutionGive customers the flexibility, speed, and scale to find what's next.ObservabilitySecuritySearchView customer storiesCustomer spotlightLearn how Cisco transforms its search experience with AIRead moreLearn how RWE powers its renewable energy trading businessRead moreLearn how Comcast boosts engineering velocity and innovationRead moreDevelopersDive in to everything related to code, forums, and groups.CommunityForumDownloadsSearch LabsConnectStay up to date with the latest tech topics, innovations, and news.EventsBlogLearnGrow your skills and open doors for future success.Getting startedElastic resourcesConsulting servicesTrainings & certificationsSecurity LabsHelpFind the support you need, no matter the topic.Contact usSupport centerSee what's happening at ElasticSee our demo galleryRead moreGet started with ElasticsearchWatch nowWhat's new in Elastic 8.12Read moreSearchPlatformElasticsearch PlatformObservability, security, and search solutions — powered by the Elasticsearch Platform.Elastic overviewELK StackSearch and analytics, data ingestion, and visualization – all at your fingertipsKibanaElasticsearchIntegrationsELK Stack overviewElastic CloudFind answers that matter with Elastic on your preferred cloud provider.Cloud overviewPartnersContact salesJoin our serverless previewSolutionsObservabilityUnify app and infrastructure visibility to proactively resolve issues.Log monitoringApplication performance monitoringInfrastructure monitoringSynthetic monitoringReal user monitoringUniversal profilingAIOpsOpenTelemetryObservability overviewSecurityProtect, investigate, and respond to cyber threats quickly and at scale.Continuous monitoringThreat huntingInvestigation and incident responseAutomated threat protectionSecurity overviewSearchAccelerate search results across any cloud and increase personalization.Generative AISearch applicationsEcommerceWebsiteWorkplace searchCustomer supportSearch overviewBy industryPublic sectorFinancial servicesTelecommunicationsHealthcareTechnologyRetail and EcommerceManufacturing and automotiveView all industriesCustomersBy solutionGive customers the flexibility, speed, and scale to find what's next.ObservabilitySecuritySearchView customer storiesCustomer spotlightLearn how Cisco transforms its search experience with AIRead moreLearn how RWE powers its renewable energy trading businessRead moreLearn how Comcast boosts engineering velocity and innovationRead moreResourcesDevelopersDive in to everything related to code, forums, and groups.CommunityForumDownloadsSearch LabsConnectStay up to date with the latest tech topics, innovations, and news.EventsBlogLearnGrow your skills and open doors for future success.Getting startedElastic resourcesConsulting servicesTrainings & certificationsSecurity LabsHelpFind the support you need, no matter the topic.Contact usSupport centerSee what's happening at ElasticSee our demo galleryRead moreGet started with ElasticsearchWatch nowWhat's new in Elastic 8.12Read morePricingDocsLanguage picker LanguageDeutschEnglishEspañolFrançais日本語한국어简体中文PortuguêsLogin LoginStart free trialContact SalesElastic StackFeaturesCapabilitiesStack securityMachine learningGeospatialVector databaseElasticsearchOverviewFeaturesElasticsearch ServiceElasticsearch searchable snapshotsElasticsearch runtime fieldsElasticsearch Relevance EngineKibanaOverviewFeaturesKibana CanvasKibana LensKibana dashboardKibana alertingElastic MapsElastic Maps ServiceIntegrationsOverviewData integrationsElastic AgentBeatsLogstashWeb crawlerContent connectorsDocsElasticsearchThe heart of the free and open Elastic StackElasticsearch is a distributed, RESTful search and analytics engine capable of addressing a growing number of use cases. As the heart of the Elastic Stack, it centrally stores your data for lightning fast search, fine‑tuned relevancy, and powerful analytics that scale with ease. Start free trialView webinarDownload ElasticsearchNew to Elasticsearch? Get up and running in no time.Watch videoLay a strong foundation for working with Elasticsearch in our Elasticsearch Engineer training.View trainingBuild advanced Elasticsearch skills for tuning relevance, text analysis, and more.View trainingNewElasticsearch Query Language (ES|QL) transforms and simplifies data investigation. The ES|QL engine delivers advanced search capabilities, improving efficiency and accelerating resolution with search and streamlined workflows.Learn moreDive deeper into the new Elasticsearch Relevance EngineThe Elasticsearch Relevance Engine™ (ESRE) is designed to power artificial intelligence-based search applications. Use ESRE to apply semantic search with superior relevance out of the box (without domain adaptation), integrate with external large language models (LLMs), implement hybrid search, and use third-party or your own transformer models.Query & AnalyzeAsk your data questions of all kindsSearch your wayElasticsearch lets you perform and combine many types of searches — structured, unstructured, geo, metric, and from a piped query language. Start simple with one question and see where it takes you.Analyze at scaleIt's one thing to find the 10 best documents to match your query. But how do you make sense of, say, a billion log lines? Elasticsearch aggregations let you zoom out to explore trends and patterns in your data.SpeedElasticsearch is fast. Really, really fast.Rapid resultsWhen you get answers instantly, your relationship with your data changes. You can afford to iterate and cover more ground.

Powerful designBeing this fast isn't easy. We've implemented inverted indices with finite state transducers for full-text querying, BKD trees for storing numeric and geo data, and a column store for analytics.

All-inclusiveAnd since everything is indexed, you're never left with index envy. You can leverage and access all of your data at ludicrously awesome speeds.ScalabilityRun it on your laptop. Or hundreds of servers with petabytes of data.Go from prototype to production seamlessly; you talk to Elasticsearch running on a single node the same way you would in a 300-node cluster.

It scales horizontally to handle kajillions of events per second, while automatically managing how indices and queries are distributed across the cluster for oh-so-smooth operations.

ResiliencyWe cover the bases while you swing for the fences.Hardware rebels. Networks partition. Elasticsearch detects failures to keep your cluster (and your data) safe and available. With cross-cluster replication, a secondary cluster can spring into action as a hot backup. Elasticsearch operates in a distributed environment designed from the ground up for perpetual peace of mind.

FLEXIBILITYStore and explore data to fit your needs.Data is constantly evolving, and it can become expensive to store and search all of it. With Elasticsearch you can balance performance and cost. Store data locally for fast queries or remotely on low-cost S3 for unlimited data. With runtime fields, you can also quickly onboard your data — and adapt to changes.

Use CasesWhat exactly can I use Elasticsearch for?Numbers, text, geo, structured, unstructured. All data types are welcome. Full-text search just scratches the surface of how companies around the world are relying on Elasticsearch to solve a variety of challenges. See a full list of solutions built directly on the Elastic Stack.

Log MonitoringFast and scalable logging that won't quit.Infrastructure MonitoringMonitor and visualize your system metrics.APMGet insight into your application performance.Synthetic MonitoringMonitor and react to availability issues.Enterprise SearchSearch and discovery experiences for any use case.MapsExplore location data in real time.

SIEMInteractive investigation and automated threat detection.Endpoint SecurityPrevent, detect, hunt for, and respond to threats.Trusted, used, and loved byDistributionDeploy your wayWherever your search takes you, we'll be there.

Elastic CloudDeploy hosted Elasticsearch and Kibana on AWS, Google Cloud, and AzureSpin up a fully loaded deployment on the cloud provider you choose. As the company behind Elasticsearch, we bring our features and support to your Elastic clusters in the cloud.See pricingStart free trialOn-PremDownload ElasticsearchGrab a fresh installation and start running Elasticsearch on your machine in just a few steps.

DownloadThe True Elasticsearch ExperienceIs it the same as Amazon’s Elasticsearch Service?Nope. There's only one.Directly from the creators, our Elasticsearch Service is the only official hosted Elasticsearch offering on AWS.

Exclusive featuresGet access to features like machine learning, an ODBC driver for BI connectivity, automated time-series data management, and alerting.EnhanceElasticsearch featuresExplore the full list of Elasticsearch features.SecurityProtect your Elasticsearch data in a robust and granular way.Learn moreMonitoringMaintain a pulse on your Elastic Stack to keep it firing on all cylinders. Learn moreAlertingGet notifications about changes in your data.

Learn moreElasticsearch SQLInteract with your data using SQL — and use ODBC and JDBC drivers to access it.Learn moreTime series data managementAutomate processes with index lifecycle management, frozen indices, and rollups.Learn moreMachine learningAutomate anomaly detection on your Elasticsearch data. Learn moreClient LibrariesInteract with Elasticsearch in the programming language you chooseElasticsearch uses standard RESTful APIs and JSON. We also build and maintain clients in many languages such as Java, Python, .NET, SQL, and PHP. Plus, our community has contributed many more. They're easy to work with, feel natural to use, and, just like Elasticsearch, don't limit what you might want to do with them.

CurlC#GoJavaJavaScriptPerlPHPPythonRubySQLcurl -H "Content-Type: application/json" -XGET

'http://localhost:9200/social-*/_search' -d '{

"query": {

"match": {

"message": "myProduct"

}

},

"aggregations": {

"top_10_states": {

"terms": {

"field": "state",

"size": 10

}

}

}

}'Learn about ElasticsearchThis webinar will cover how to get started, which includes deploying, managing, and analyzing data in Elasticsearch.Getting startedFollow usAbout usAbout ElasticOur storyLeadershipDE&IBlogJoin usCareersCareer portalPressPress releasesNews articlesPartnersFind a partnerPartner loginRequest accessBecome a partnerTrust & SecurityTrust centerEthicsPoint portalECCN reportEthics emailInvestor relationsInvestor resourcesGovernanceFinancialsStockEXCELLENCE AWARDSPrevious winnersElasticON TourBecome a sponsorAll eventsAbout usAbout ElasticOur storyLeadershipDE&IBlogJoin usCareersCareer portalPressPress releasesNews articlesPartnersFind a partnerPartner loginRequest accessBecome a partnerTrust & SecurityTrust centerEthicsPoint portalECCN reportEthics emailInvestor relationsInvestor resourcesGovernanceFinancialsStockEXCELLENCE AWARDSPrevious winnersElasticON TourBecome a sponsorAll eventsTrademarksTerms of UsePrivacySitemap© . Elasticsearch B.V. All Rights ReservedElastic, Elasticsearch and other related marks are trademarks, logos or registered trademarks of Elasticsearch B.V. in the United States and other countries.Apache, Apache Lucene, Apache Hadoop, Hadoop, HDFS and the yellow elephant logo are trademarks of the Apache Software Foundation in the United States and/or other countries. All other brand names, product names, or trademarks belong to their respective owne

2万字详解,彻底讲透 全文搜索引擎 Elasticsearch - 知乎

2万字详解,彻底讲透 全文搜索引擎 Elasticsearch - 知乎首发于炮哥和他的Java切换模式写文章登录/注册2万字详解,彻底讲透 全文搜索引擎 Elasticsearch老炮说Java由于近期在公司内部做了一次 Elasticsearch 的分享,所以本篇主要是做一个总结,希望通过这篇文章能让读者大致了解 Elasticsearch 是做什么的以及它的使用和基本原理。生活中的数据搜索引擎是对数据的检索,所以我们先从生活中的数据说起。我们生活中的数据总体分为两种:结构化数据非结构化数据结构化数据: 也称作行数据,是由二维表结构来逻辑表达和实现的数据,严格地遵循数据格式与长度规范,主要通过关系型数据库进行存储和管理。指具有固定格式或有限长度的数据,如数据库,元数据等。非结构化数据: 又可称为全文数据,不定长或无固定格式,不适于由数据库二维表来表现,包括所有格式的办公文档、XML、HTML、Word 文档,邮件,各类报表、图片和咅频、视频信息等。说明:如果要更细致的区分的话,XML、HTML 可划分为半结构化数据。因为它们也具有自己特定的标签格式,所以既可以根据需要按结构化数据来处理,也可抽取出纯文本按非结构化数据来处理。根据两种数据分类,搜索也相应的分为两种:结构化数据搜索非结构化数据搜索对于结构化数据,因为它们具有特定的结构,所以我们一般都是可以通过关系型数据库(MySQL,Oracle 等)的二维表(Table)的方式存储和搜索,也可以建立索引。对于非结构化数据,也即对全文数据的搜索主要有两种方法:顺序扫描全文检索顺序扫描: 通过文字名称也可了解到它的大概搜索方式,即按照顺序扫描的方式查询特定的关键字。例如给你一张报纸,让你找到该报纸中“平安”的文字在哪些地方出现过。你肯定需要从头到尾把报纸阅读扫描一遍然后标记出关键字在哪些版块出现过以及它的出现位置。这种方式无疑是最耗时的最低效的,如果报纸排版字体小,而且版块较多甚至有多份报纸,等你扫描完你的眼睛也差不多了。全文搜索: 对非结构化数据顺序扫描很慢,我们是否可以进行优化?把我们的非结构化数据想办法弄得有一定结构不就行了吗?将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。这种方式就构成了全文检索的基本思路。这部分从非结构化数据中提取出的然后重新组织的信息,我们称之为索引。这种方式的主要工作量在前期索引的创建,但是对于后期搜索却是快速高效的。先说说 Lucene通过对生活中数据的类型作了一个简短了解之后,我们知道关系型数据库的 SQL 检索是处理不了这种非结构化数据的。这种非结构化数据的处理需要依赖全文搜索,而目前市场上开放源代码的最好全文检索引擎工具包就属于 Apache 的 Lucene了。但是 Lucene 只是一个工具包,它不是一个完整的全文检索引擎。Lucene 的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。目前以 Lucene 为基础建立的开源可用全文搜索引擎主要是 Solr 和 Elasticsearch。Solr 和 Elasticsearch 都是比较成熟的全文搜索引擎,能完成的功能和性能也基本一样。但是 ES 本身就具有分布式的特性和易安装使用的特点,而 Solr 的分布式需要借助第三方来实现,例如通过使用 ZooKeeper 来达到分布式协调管理。不管是 Solr 还是 Elasticsearch 底层都是依赖于 Lucene,而 Lucene 能实现全文搜索主要是因为它实现了倒排索引的查询结构。如何理解倒排索引呢? 假如现有三份数据文档,文档的内容如下分别是:Java is the best programming language.PHP is the best programming language.Javascript is the best programming language.为了创建倒排索引,我们通过分词器将每个文档的内容域拆分成单独的词(我们称它为词条或 Term),创建一个包含所有不重复词条的排序列表,然后列出每个词条出现在哪个文档。结果如下所示:Term Doc_1 Doc_2 Doc_3

-------------------------------------

Java | X | |

is | X | X | X

the | X | X | X

best | X | X | X

programming | x | X | X

language | X | X | X

PHP | | X |

Javascript | | | X

-------------------------------------

这种结构由文档中所有不重复词的列表构成,对于其中每个词都有一个文档列表与之关联。这种由属性值来确定记录的位置的结构就是倒排索引。带有倒排索引的文件我们称为倒排文件。我们将上面的内容转换为图的形式来说明倒排索引的结构信息,如下图所示:其中主要有如下几个核心术语需要理解:词条(Term): 索引里面最小的存储和查询单元,对于英文来说是一个单词,对于中文来说一般指分词后的一个词。词典(Term Dictionary): 或字典,是词条 Term 的集合。搜索引擎的通常索引单位是单词,单词词典是由文档集合中出现过的所有单词构成的字符串集合,单词词典内每条索引项记载单词本身的一些信息以及指向“倒排列表”的指针。倒排表(Post list): 一个文档通常由多个词组成,倒排表记录的是某个词在哪些文档里出现过以及出现的位置。每条记录称为一个倒排项(Posting)。倒排表记录的不单是文档编号,还存储了词频等信息。倒排文件(Inverted File): 所有单词的倒排列表往往顺序地存储在磁盘的某个文件里,这个文件被称之为倒排文件,倒排文件是存储倒排索引的物理文件。从上图我们可以了解到倒排索引主要由两个部分组成:词典倒排文件词典和倒排表是 Lucene 中很重要的两种数据结构,是实现快速检索的重要基石。词典和倒排文件是分两部分存储的,词典在内存中而倒排文件存储在磁盘上。ES 核心概念一些基础知识的铺垫之后我们正式进入今天的主角 Elasticsearch 的介绍。ES 是使用 Java 编写的一种开源搜索引擎,它在内部使用 Lucene 做索引与搜索,通过对 Lucene 的封装,隐藏了 Lucene 的复杂性,取而代之的提供一套简单一致的 RESTful API。然而,Elasticsearch 不仅仅是 Lucene,并且也不仅仅只是一个全文搜索引擎。它可以被下面这样准确的形容:一个分布式的实时文档存储,每个字段可以被索引与搜索。一个分布式实时分析搜索引擎。能胜任上百个服务节点的扩展,并支持 PB 级别的结构化或者非结构化数据。官网对 Elasticsearch 的介绍是 Elasticsearch 是一个分布式、可扩展、近实时的搜索与数据分析引擎。我们通过一些核心概念来看下 Elasticsearch 是如何做到分布式,可扩展和近实时搜索的。集群(Cluster)ES 的集群搭建很简单,不需要依赖第三方协调管理组件,自身内部就实现了集群的管理功能。ES 集群由一个或多个 Elasticsearch 节点组成,每个节点配置相同的 cluster.name 即可加入集群,默认值为 “elasticsearch”。确保不同的环境中使用不同的集群名称,否则最终会导致节点加入错误的集群。一个 Elasticsearch 服务启动实例就是一个节点(Node)。节点通过 node.name 来设置节点名称,如果不设置则在启动时给节点分配一个随机通用唯一标识符作为名称。①发现机制那么有一个问题,ES 内部是如何通过一个相同的设置 cluster.name 就能将不同的节点连接到同一个集群的?答案是 Zen Discovery。Zen Discovery 是 Elasticsearch 的内置默认发现模块(发现模块的职责是发现集群中的节点以及选举 Master 节点)。它提供单播和基于文件的发现,并且可以扩展为通过插件支持云环境和其他形式的发现。Zen Discovery 与其他模块集成,例如,节点之间的所有通信都使用 Transport 模块完成。节点使用发现机制通过 Ping 的方式查找其他节点。Elasticsearch 默认被配置为使用单播发现,以防止节点无意中加入集群。只有在同一台机器上运行的节点才会自动组成集群。如果集群的节点运行在不同的机器上,使用单播,你可以为 Elasticsearch 提供一些它应该去尝试连接的节点列表。当一个节点联系到单播列表中的成员时,它就会得到整个集群所有节点的状态,然后它会联系 Master 节点,并加入集群。这意味着单播列表不需要包含集群中的所有节点, 它只是需要足够的节点,当一个新节点联系上其中一个并且说上话就可以了。如果你使用 Master 候选节点作为单播列表,你只要列出三个就可以了。这个配置在 elasticsearch.yml 文件中:discovery.zen.ping.unicast.hosts: ["host1", "host2:port"]

节点启动后先 Ping ,如果 discovery.zen.ping.unicast.hosts 有设置,则 Ping 设置中的 Host ,否则尝试 ping localhost 的几个端口。Elasticsearch 支持同一个主机启动多个节点,Ping 的 Response 会包含该节点的基本信息以及该节点认为的 Master 节点。选举开始,先从各节点认为的 Master 中选,规则很简单,按照 ID 的字典序排序,取第一个。如果各节点都没有认为的 Master ,则从所有节点中选择,规则同上。这里有个限制条件就是 discovery.zen.minimum_master_nodes ,如果节点数达不到最小值的限制,则循环上述过程,直到节点数足够可以开始选举。最后选举结果是肯定能选举出一个 Master ,如果只有一个 Local 节点那就选出的是自己。如果当前节点是 Master ,则开始等待节点数达到 discovery.zen.minimum_master_nodes,然后提供服务。如果当前节点不是 Master ,则尝试加入 Master 。Elasticsearch 将以上服务发现以及选主的流程叫做 Zen Discovery 。由于它支持任意数目的集群( 1- N ),所以不能像 Zookeeper 那样限制节点必须是奇数,也就无法用投票的机制来选主,而是通过一个规则。只要所有的节点都遵循同样的规则,得到的信息都是对等的,选出来的主节点肯定是一致的。但分布式系统的问题就出在信息不对等的情况,这时候很容易出现脑裂(Split-Brain)的问题。大多数解决方案就是设置一个 Quorum 值,要求可用节点必须大于 Quorum(一般是超过半数节点),才能对外提供服务。而 Elasticsearch 中,这个 Quorum 的配置就是 discovery.zen.minimum_master_nodes 。②节点的角色每个节点既可以是候选主节点也可以是数据节点,通过在配置文件 ../config/elasticsearch.yml 中设置即可,默认都为 true。node.master: true //是否候选主节点

node.data: true //是否数据节点

数据节点负责数据的存储和相关的操作,例如对数据进行增、删、改、查和聚合等操作,所以数据节点(Data 节点)对机器配置要求比较高,对 CPU、内存和 I/O 的消耗很大。通常随着集群的扩大,需要增加更多的数据节点来提高性能和可用性。候选主节点可以被选举为主节点(Master 节点),集群中只有候选主节点才有选举权和被选举权,其他节点不参与选举的工作。主节点负责创建索引、删除索引、跟踪哪些节点是群集的一部分,并决定哪些分片分配给相关的节点、追踪集群中节点的状态等,稳定的主节点对集群的健康是非常重要的。一个节点既可以是候选主节点也可以是数据节点,但是由于数据节点对 CPU、内存核 I/O 消耗都很大。所以如果某个节点既是数据节点又是主节点,那么可能会对主节点产生影响从而对整个集群的状态产生影响。因此为了提高集群的健康性,我们应该对 Elasticsearch 集群中的节点做好角色上的划分和隔离。可以使用几个配置较低的机器群作为候选主节点群。主节点和其他节点之间通过 Ping 的方式互检查,主节点负责 Ping 所有其他节点,判断是否有节点已经挂掉。其他节点也通过 Ping 的方式判断主节点是否处于可用状态。虽然对节点做了角色区分,但是用户的请求可以发往任何一个节点,并由该节点负责分发请求、收集结果等操作,而不需要主节点转发。这种节点可称之为协调节点,协调节点是不需要指定和配置的,集群中的任何节点都可以充当协调节点的角色。③脑裂现象同时如果由于网络或其他原因导致集群中选举出多个 Master 节点,使得数据更新时出现不一致,这种现象称之为脑裂,即集群中不同的节点对于 Master 的选择出现了分歧,出现了多个 Master 竞争。“脑裂”问题可能有以下几个原因造成:网络问题: 集群间的网络延迟导致一些节点访问不到 Master,认为 Master 挂掉了从而选举出新的 Master,并对 Master 上的分片和副本标红,分配新的主分片。节点负载: 主节点的角色既为 Master 又为 Data,访问量较大时可能会导致 ES 停止响应(假死状态)造成大面积延迟,此时其他节点得不到主节点的响应认为主节点挂掉了,会重新选取主节点。内存回收: 主节点的角色既为 Master 又为 Data,当 Data 节点上的 ES 进程占用的内存较大,引发 JVM 的大规模内存回收,造成 ES 进程失去响应。为了避免脑裂现象的发生,我们可以从原因着手通过以下几个方面来做出优化措施:适当调大响应时间,减少误判。 通过参数 discovery.zen.ping_timeout 设置节点状态的响应时间,默认为 3s,可以适当调大。如果 Master 在该响应时间的范围内没有做出响应应答,判断该节点已经挂掉了。调大参数(如 6s,discovery.zen.ping_timeout:6),可适当减少误判。选举触发。 我们需要在候选集群中的节点的配置文件中设置参数 discovery.zen.munimum_master_nodes 的值。这个参数表示在选举主节点时需要参与选举的候选主节点的节点数,默认值是 1,官方建议取值(master_eligibel_nodes2)+1,其中 master_eligibel_nodes 为候选主节点的个数。这样做既能防止脑裂现象的发生,也能最大限度地提升集群的高可用性,因为只要不少于 discovery.zen.munimum_master_nodes 个候选节点存活,选举工作就能正常进行。当小于这个值的时候,无法触发选举行为,集群无法使用,不会造成分片混乱的情况。角色分离。 即是上面我们提到的候选主节点和数据节点进行角色分离,这样可以减轻主节点的负担,防止主节点的假死状态发生,减少对主节点“已死”的误判。分片(Shards)ES 支持 PB 级全文搜索,当索引上的数据量太大的时候,ES 通过水平拆分的方式将一个索引上的数据拆分出来分配到不同的数据块上,拆分出来的数据库块称之为一个分片。这类似于 MySQL 的分库分表,只不过 MySQL 分库分表需要借助第三方组件而 ES 内部自身实现了此功能。在一个多分片的索引中写入数据时,通过路由来确定具体写入哪一个分片中,所以在创建索引的时候需要指定分片的数量,并且分片的数量一旦确定就不能修改。分片的数量和下面介绍的副本数量都是可以通过创建索引时的 Settings 来配置,ES 默认为一个索引创建 5 个主分片, 并分别为每个分片创建一个副本。PUT /myIndex

{

"settings" : {

"number_of_shards" : 5,

"number_of_replicas" : 1

}

}

ES 通过分片的功能使得索引在规模上和性能上都得到提升,每个分片都是 Lucene 中的一个索引文件,每个分片必须有一个主分片和零到多个副本。副本(Replicas)副本就是对分片的 Copy,每个主分片都有一个或多个副本分片,当主分片异常时,副本可以提供数据的查询等操作。主分片和对应的副本分片是不会在同一个节点上的,所以副本分片数的最大值是 N-1(其中 N 为节点数)。对文档的新建、索引和删除请求都是写操作,必须在主分片上面完成之后才能被复制到相关的副本分片。ES 为了提高写入的能力这个过程是并发写的,同时为了解决并发写的过程中数据冲突的问题,ES 通过乐观锁的方式控制,每个文档都有一个 _version (版本)号,当文档被修改时版本号递增。一旦所有的副本分片都报告写成功才会向协调节点报告成功,协调节点向客户端报告成功。从上图可以看出为了达到高可用,Master 节点会避免将主分片和副本分片放在同一个节点上。假设这时节点 Node1 服务宕机了或者网络不可用了,那么主节点上主分片 S0 也就不可用了。幸运的是还存在另外两个节点能正常工作,这时 ES 会重新选举新的主节点,而且这两个节点上存在我们所需要的 S0 的所有数据。我们会将 S0 的副本分片提升为主分片,这个提升主分片的过程是瞬间发生的。此时集群的状态将会为 Yellow。为什么我们集群状态是 Yellow 而不是 Green 呢?虽然我们拥有所有的 2 个主分片,但是同时设置了每个主分片需要对应两份副本分片,而此时只存在一份副本分片。所以集群不能为 Green 的状态。如果我们同样关闭了 Node2 ,我们的程序依然可以保持在不丢失任何数据的情况下运行,因为 Node3 为每一个分片都保留着一份副本。如果我们重新启动 Node1 ,集群可以将缺失的副本分片再次进行分配,那么集群的状态又将恢复到原来的正常状态。如果 Node1 依然拥有着之前的分片,它将尝试去重用它们,只不过这时 Node1 节点上的分片不再是主分片而是副本分片了,如果期间有更改的数据只需要从主分片上复制修改的数据文件即可。小结:将数据分片是为了提高可处理数据的容量和易于进行水平扩展,为分片做副本是为了提高集群的稳定性和提高并发量。副本是乘法,越多消耗越大,但也越保险。分片是除法,分片越多,单分片数据就越少也越分散。副本越多,集群的可用性就越高,但是由于每个分片都相当于一个 Lucene 的索引文件,会占用一定的文件句柄、内存及 CPU。并且分片间的数据同步也会占用一定的网络带宽,所以索引的分片数和副本数也不是越多越好。映射(Mapping)映射是用于定义 ES 对索引中字段的存储类型、分词方式和是否存储等信息,就像数据库中的 Schema ,描述了文档可能具有的字段或属性、每个字段的数据类型。只不过关系型数据库建表时必须指定字段类型,而 ES 对于字段类型可以不指定然后动态对字段类型猜测,也可以在创建索引时具体指定字段的类型。对字段类型根据数据格式自动识别的映射称之为动态映射(Dynamic Mapping),我们创建索引时具体定义字段类型的映射称之为静态映射或显示映射(Explicit Mapping)。在讲解动态映射和静态映射的使用前,我们先来了解下 ES 中的数据有哪些字段类型?之后我们再讲解为什么我们创建索引时需要建立静态映射而不使用动态映射。ES(v6.8)中字段数据类型主要有以下几类:Text 用于索引全文值的字段,例如电子邮件正文或产品说明。这些字段是被分词的,它们通过分词器传递 ,以在被索引之前将字符串转换为单个术语的列表。分析过程允许 Elasticsearch 搜索单个单词中每个完整的文本字段。文本字段不用于排序,很少用于聚合。Keyword 用于索引结构化内容的字段,例如电子邮件地址,主机名,状态代码,邮政编码或标签。它们通常用于过滤,排序,和聚合。Keyword 字段只能按其确切值进行搜索。通过对字段类型的了解我们知道有些字段需要明确定义的,例如某个字段是 Text 类型还是 Keyword 类型差别是很大的,时间字段也许我们需要指定它的时间格式,还有一些字段我们需要指定特定的分词器等等。如果采用动态映射是不能精确做到这些的,自动识别常常会与我们期望的有些差异。所以创建索引的时候一个完整的格式应该是指定分片和副本数以及 Mapping 的定义,如下:PUT my_index

{

"settings" : {

"number_of_shards" : 5,

"number_of_replicas" : 1

}

"mappings": {

"_doc": {

"properties": {

"title": { "type": "text" },

"name": { "type": "text" },

"age": { "type": "integer" },

"created": {

"type": "date",

"format": "strict_date_optional_time||epoch_millis"

}

}

}

}

}

ES 的基本使用在决定使用 Elasticsearch 的时候首先要考虑的是版本问题,Elasticsearch (排除 0.x 和 1.x)目前有如下常用的稳定的主版本:2.x,5.x,6.x,7.x(current)。你可能会发现没有 3.x 和 4.x,ES 从 2.4.6 直接跳到了 5.0.0。其实是为了 ELK(ElasticSearch,Logstash,Kibana)技术栈的版本统一,免的给用户带来混乱。在 Elasticsearch 是 2.x (2.x 的最后一版 2.4.6 的发布时间是 July 25, 2017) 的情况下,Kibana 已经是 4.x(Kibana 4.6.5 的发布时间是 July 25, 2017)。那么在 Kibana 的下一主版本肯定是 5.x 了,所以 Elasticsearch 直接将自己的主版本发布为 5.0.0 了。统一之后,我们选版本就不会犹豫困惑了,我们选定 Elasticsearch 的版本后再选择相同版本的 Kibana 就行了,不用担忧版本不兼容的问题。Elasticsearch 是使用 Java 构建,所以除了注意 ELK 技术的版本统一,我们在选择 Elasticsearch 的版本的时候还需要注意 JDK 的版本。因为每个大版本所依赖的 JDK 版本也不同,目前 7.2 版本已经可以支持 JDK11。安装使用①下载和解压 Elasticsearch,无需安装解压后即可用,解压后目录如上图:bin:二进制系统指令目录,包含启动命令和安装插件命令等。config:配置文件目录。data:数据存储目录。lib:依赖包目录。logs:日志文件目录。modules:模块库,例如 x-pack 的模块。plugins:插件目录。②安装目录下运行 bin/elasticsearch 来启动 ES。③默认在 9200 端口运行,请求 curl http://localhost:9200/ 或者浏览器输入 http://localhost:9200,得到一个 JSON 对象,其中包含当前节点、集群、版本等信息。{

"name" : "U7fp3O9",

"cluster_name" : "elasticsearch",

"cluster_uuid" : "-Rj8jGQvRIelGd9ckicUOA",

"version" : {

"number" : "6.8.1",

"build_flavor" : "default",

"build_type" : "zip",

"build_hash" : "1fad4e1",

"build_date" : "2019-06-18T13:16:52.517138Z",

"build_snapshot" : false,

"lucene_version" : "7.7.0",

"minimum_wire_compatibility_version" : "5.6.0",

"minimum_index_compatibility_version" : "5.0.0"

},

"tagline" : "You Know, for Search"

}

集群健康状态要检查群集运行状况,我们可以在 Kibana 控制台中运行以下命令 GET /_cluster/health,得到如下信息:{

"cluster_name" : "wujiajian",

"status" : "yellow",

"timed_out" : false,

"number_of_nodes" : 1,

"number_of_data_nodes" : 1,

"active_primary_shards" : 9,

"active_shards" : 9,

"relocating_shards" : 0,

"initializing_shards" : 0,

"unassigned_shards" : 5,

"delayed_unassigned_shards" : 0,

"number_of_pending_tasks" : 0,

"number_of_in_flight_fetch" : 0,

"task_max_waiting_in_queue_millis" : 0,

"active_shards_percent_as_number" : 64.28571428571429

}

集群状态通过 绿,黄,红 来标识:绿色:集群健康完好,一切功能齐全正常,所有分片和副本都可以正常工作。黄色:预警状态,所有主分片功能正常,但至少有一个副本是不能正常工作的。此时集群是可以正常工作的,但是高可用性在某种程度上会受影响。红色:集群不可正常使用。某个或某些分片及其副本异常不可用,这时集群的查询操作还能执行,但是返回的结果会不准确。对于分配到这个分片的写入请求将会报错,最终会导致数据的丢失。当集群状态为红色时,它将会继续从可用的分片提供搜索请求服务,但是你需要尽快修复那些未分配的分片。ES 机制原理ES 的基本概念和基本操作介绍完了之后,我们可能还有很多疑惑:它们内部是如何运行的?主分片和副本分片是如何同步的?创建索引的流程是什么样的?ES 如何将索引数据分配到不同的分片上的?以及这些索引数据是如何存储的?为什么说 ES 是近实时搜索引擎而文档的 CRUD (创建-读取-更新-删除) 操作是实时的?以及 Elasticsearch 是怎样保证更新被持久化在断电时也不丢失数据?还有为什么删除文档不会立刻释放空间?带着这些疑问我们进入接下来的内容。写索引原理下图描述了 3 个节点的集群,共拥有 12 个分片,其中有 4 个主分片(S0、S1、S2、S3)和 8 个副本分片(R0、R1、R2、R3),每个主分片对应两个副本分片,节点 1 是主节点(Master 节点)负责整个集群的状态。写索引是只能写在主分片上,然后同步到副本分片。这里有四个主分片,一条数据 ES 是根据什么规则写到特定分片上的呢?这条索引数据为什么被写到 S0 上而不写到 S1 或 S2 上?那条数据为什么又被写到 S3 上而不写到 S0 上了?首先这肯定不会是随机的,否则将来要获取文档的时候我们就不知道从何处寻找了。实际上,这个过程是根据下面这个公式决定的:shard = hash(routing) % number_of_primary_shards

Routing 是一个可变值,默认是文档的 _id ,也可以设置成一个自定义的值。Routing 通过 Hash 函数生成一个数字,然后这个数字再除以 number_of_primary_shards (主分片的数量)后得到余数。这个在 0 到 number_of_primary_shards-1 之间的余数,就是我们所寻求的文档所在分片的位置。这就解释了为什么我们要在创建索引的时候就确定好主分片的数量并且永远不会改变这个数量:因为如果数量变化了,那么所有之前路由的值都会无效,文档也再也找不到了。由于在 ES 集群中每个节点通过上面的计算公式都知道集群中的文档的存放位置,所以每个节点都有处理读写请求的能力。在一个写请求被发送到某个节点后,该节点即为前面说过的协调节点,协调节点会根据路由公式计算出需要写到哪个分片上,再将请求转发到该分片的主分片节点上。假如此时数据通过路由计算公式取余后得到的值是 shard=hash(routing)%4=0。则具体流程如下:客户端向 ES1 节点(协调节点)发送写请求,通过路由计算公式得到值为 0,则当前数据应被写到主分片 S0 上。ES1 节点将请求转发到 S0 主分片所在的节点 ES3,ES3 接受请求并写入到磁盘。并发将数据复制到两个副本分片 R0 上,其中通过乐观并发控制数据的冲突。一旦所有的副本分片都报告成功,则节点 ES3 将向协调节点报告成功,协调节点向客户端报告成功。存储原理上面介绍了在 ES 内部索引的写处理流程,这个流程是在 ES 的内存中执行的,数据被分配到特定的分片和副本上之后,最终是存储到磁盘上的,这样在断电的时候就不会丢失数据。具体的存储路径可在配置文件 ../config/elasticsearch.yml 中进行设置,默认存储在安装目录的 Data 文件夹下。建议不要使用默认值,因为若 ES 进行了升级,则有可能导致数据全部丢失:path.data: /path/to/data //索引数据

path.logs: /path/to/logs //日志记录

①分段存储索引文档以段的形式存储在磁盘上,何为段?索引文件被拆分为多个子文件,则每个子文件叫作段,每一个段本身都是一个倒排索引,并且段具有不变性,一旦索引的数据被写入硬盘,就不可再修改。在底层采用了分段的存储模式,使它在读写时几乎完全避免了锁的出现,大大提升了读写性能。段被写入到磁盘后会生成一个提交点,提交点是一个用来记录所有提交后段信息的文件。一个段一旦拥有了提交点,就说明这个段只有读的权限,失去了写的权限。相反,当段在内存中时,就只有写的权限,而不具备读数据的权限,意味着不能被检索。段的概念提出主要是因为:在早期全文检索中为整个文档集合建立了一个很大的倒排索引,并将其写入磁盘中。如果索引有更新,就需要重新全量创建一个索引来替换原来的索引。这种方式在数据量很大时效率很低,并且由于创建一次索引的成本很高,所以对数据的更新不能过于频繁,也就不能保证时效性。索引文件分段存储并且不可修改,那么新增、更新和删除如何处理呢?新增,新增很好处理,由于数据是新的,所以只需要对当前文档新增一个段就可以了。删除,由于不可修改,所以对于删除操作,不会把文档从旧的段中移除而是通过新增一个 .del 文件,文件中会列出这些被删除文档的段信息。这个被标记删除的文档仍然可以被查询匹配到, 但它会在最终结果被返回前从结果集中移除。更新,不能修改旧的段来进行反映文档的更新,其实更新相当于是删除和新增这两个动作组成。会将旧的文档在 .del 文件中标记删除,然后文档的新版本被索引到一个新的段中。可能两个版本的文档都会被一个查询匹配到,但被删除的那个旧版本文档在结果集返回前就会被移除。段被设定为不可修改具有一定的优势也有一定的缺点,优势主要表现在:不需要锁。如果你从来不更新索引,你就不需要担心多进程同时修改数据的问题。一旦索引被读入内核的文件系统缓存,便会留在哪里,由于其不变性。只要文件系统缓存中还有足够的空间,那么大部分读请求会直接请求内存,而不会命中磁盘。这提供了很大的性能提升。其它缓存(像 Filter 缓存),在索引的生命周期内始终有效。它们不需要在每次数据改变时被重建,因为数据不会变化。写入单个大的倒排索引允许数据被压缩,减少磁盘 I/O 和需要被缓存到内存的索引的使用量。段的不变性的缺点如下:当对旧数据进行删除时,旧数据不会马上被删除,而是在 .del 文件中被标记为删除。而旧数据只能等到段更新时才能被移除,这样会造成大量的空间浪费。若有一条数据频繁的更新,每次更新都是新增新的标记旧的,则会有大量的空间浪费。每次新增数据时都需要新增一个段来存储数据。当段的数量太多时,对服务器的资源例如文件句柄的消耗会非常大。在查询的结果中包含所有的结果集,需要排除被标记删除的旧数据,这增加了查询的负担。②延迟写策略介绍完了存储的形式,那么索引写入到磁盘的过程是怎样的?是否是直接调 Fsync 物理性地写入磁盘?答案是显而易见的,如果是直接写入到磁盘上,磁盘的 I/O 消耗上会严重影响性能。那么当写数据量大的时候会造成 ES 停顿卡死,查询也无法做到快速响应。如果真是这样 ES 也就不会称之为近实时全文搜索引擎了。为了提升写的性能,ES 并没有每新增一条数据就增加一个段到磁盘上,而是采用延迟写的策略。每当有新增的数据时,就将其先写入到内存中,在内存和磁盘之间是文件系统缓存。当达到默认的时间(1 秒钟)或者内存的数据达到一定量时,会触发一次刷新(Refresh),将内存中的数据生成到一个新的段上并缓存到文件缓存系统 上,稍后再被刷新到磁盘中并生成提交点。这里的内存使用的是 ES 的 JVM 内存,而文件缓存系统使用的是操作系统的内存。新的数据会继续的被写入内存,但内存中的数据并不是以段的形式存储的,因此不能提供检索功能。由内存刷新到文件缓存系统的时候会生成新的段,并将段打开以供搜索使用,而不需要等到被刷新到磁盘。在 Elasticsearch 中,写入和打开一个新段的轻量的过程叫做 Refresh (即内存刷新到文件缓存系统)。默认情况下每个分片会每秒自动刷新一次。这就是为什么我们说 Elasticsearch 是近实时搜索,因为文档的变化并不是立即对搜索可见,但会在一秒之内变为可见。我们也可以手动触发 Refresh,POST /_refresh 刷新所有索引,POST /nba/_refresh 刷新指定的索引。Tips:尽管刷新是比提交轻量很多的操作,它还是会有性能开销。当写测试的时候, 手动刷新很有用,但是不要在生产>环境下每次索引一个文档都去手动刷新。而且并不是所有的情况都需要每秒刷新。可能你正在使用 Elasticsearch 索引大量的日志文件, 你可能想优化索引速度而不是>近实时搜索。这时可以在创建索引时在 Settings 中通过调大 refresh_interval = "30s" 的值 , 降低每个索引的刷新频率,设值时需要注意后面带上时间单位,否则默认是毫秒。当 refresh_interval=-1 时表示关闭索引的自动刷新。虽然通过延时写的策略可以减少数据往磁盘上写的次数提升了整体的写入能力,但是我们知道文件缓存系统也是内存空间,属于操作系统的内存,只要是内存都存在断电或异常情况下丢失数据的危险。为了避免丢失数据,Elasticsearch 添加了事务日志(Translog),事务日志记录了所有还没有持久化到磁盘的数据。添加了事务日志后整个写索引的流程如上图所示:一个新文档被索引之后,先被写入到内存中,但是为了防止数据的丢失,会追加一份数据到事务日志中。不断有新的文档被写入到内存,同时也都会记录到事务日志中。这时新数据还不能被检索和查询。当达到默认的刷新时间或内存中的数据达到一定量后,会触发一次 Refresh,将内存中的数据以一个新段形式刷新到文件缓存系统中并清空内存。这时虽然新段未被提交到磁盘,但是可以提供文档的检索功能且不能被修改。随着新文档索引不断被写入,当日志数据大小超过 512M 或者时间超过 30 分钟时,会触发一次 Flush。内存中的数据被写入到一个新段同时被写入到文件缓存系统,文件系统缓存中数据通过 Fsync 刷新到磁盘中,生成提交点,日志文件被删除,创建一个空的新日志。通过这种方式当断电或需要重启时,ES 不仅要根据提交点去加载已经持久化过的段,还需要工具 Translog 里的记录,把未持久化的数据重新持久化到磁盘上,避免了数据丢失的可能。③段合并由于自动刷新流程每秒会创建一个新的段 ,这样会导致短时间内的段数量暴增。而段数目太多会带来较大的麻烦。每一个段都会消耗文件句柄、内存和 CPU 运行周期。更重要的是,每个搜索请求都必须轮流检查每个段然后合并查询结果,所以段越多,搜索也就越慢。Elasticsearch 通过在后台定期进行段合并来解决这个问题。小的段被合并到大的段,然后这些大的段再被合并到更大的段。段合并的时候会将那些旧的已删除文档从文件系统中清除。被删除的文档不会被拷贝到新的大段中。合并的过程中不会中断索引和搜索。图片段合并在进行索引和搜索时会自动进行,合并进程选择一小部分大小相似的段,并且在后台将它们合并到更大的段中,这些段既可以是未提交的也可以是已提交的。合并结束后老的段会被删除,新的段被 Flush 到磁盘,同时写入一个包含新段且排除旧的和较小的段的新提交点,新的段被打开可以用来搜索。段合并的计算量庞大, 而且还要吃掉大量磁盘 I/O,段合并会拖累写入速率,如果任其发展会影响搜索性能。Elasticsearch 在默认情况下会对合并流程进行资源限制,所以搜索仍然有足够的资源很好地执行。性能优化存储设备磁盘在现代服务器上通常都是瓶颈。Elasticsearch 重度使用磁盘,你的磁盘能处理的吞吐量越大,你的节点就越稳定。这里有一些优化磁盘 I/O 的技巧:使用 SSD。就像其他地方提过的, 他们比机械磁盘优秀多了。使用 RAID 0。条带化 RAID 会提高磁盘 I/O,代价显然就是当一块硬盘故障时整个就故障了。不要使用镜像或者奇偶校验 RAID 因为副本已经提供了这个功能。另外,使用多块硬盘,并允许 Elasticsearch 通过多个 path.data 目录配置把数据条带化分配到它们上面。不要使用远程挂载的存储,比如 NFS 或者 SMB/CIFS。这个引入的延迟对性能来说完全是背道而驰的。如果你用的是 EC2,当心 EBS。即便是基于 SSD 的 EBS,通常也比本地实例的存储要慢。内部索引优化Elasticsearch 为了能快速找到某个 Term,先将所有的 Term 排个序,然后根据二分法查找 Term,时间复杂度为 logN,就像通过字典查找一样,这就是 Term Dictionary。现在再看起来,似乎和传统数据库通过 B-Tree 的方式类似。但是如果 Term 太多,Term Dictionary 也会很大,放内存不现实,于是有了 Term Index。就像字典里的索引页一样,A 开头的有哪些 Term,分别在哪页,可以理解 Term Index是一棵树。这棵树不会包含所有的 Term,它包含的是 Term 的一些前缀。通过 Term Index 可以快速地定位到 Term Dictionary 的某个 Offset,然后从这个位置再往后顺序查找。在内存中用 FST 方式压缩 Term Index,FST 以字节的方式存储所有的 Term,这种压缩方式可以有效的缩减存储空间,使得 Term Index 足以放进内存,但这种方式也会导致查找时需要更多的 CPU 资源。对于存储在磁盘上的倒排表同样也采用了压缩技术减少存储所占用的空间。调整配置参数调整配置参数建议如下:给每个文档指定有序的具有压缩良好的序列模式 ID,避免随机的 UUID-4 这样的 ID,这样的 ID 压缩比很低,会明显拖慢 Lucene。对于那些不需要聚合和排序的索引字段禁用 Doc values。Doc Values 是有序的基于 document=>field value 的映射列表。不需要做模糊检索的字段使用 Keyword 类型代替 Text 类型,这样可以避免在建立索引前对这些文本进行分词。如果你的搜索结果不需要近实时的准确度,考虑把每个索引的 index.refresh_interval 改到 30s 。如果你是在做大批量导入,导入期间你可以通过设置这个值为 -1 关掉刷新,还可以通过设置 index.number_of_replicas: 0 关闭副本。别忘记在完工的时候重新开启它。避免深度分页查询建议使用 Scroll 进行分页查询。普通分页查询时,会创建一个 from+size 的空优先队列,每个分片会返回 from+size 条数据,默认只包含文档 ID 和得分 Score 给协调节点。如果有 N 个分片,则协调节点再对(from+size)×n 条数据进行二次排序,然后选择需要被取回的文档。当 from 很大时,排序过程会变得很沉重,占用 CPU 资源严重。减少映射字段,只提供需要检索,聚合或排序的字段。其他字段可存在其他存储设备上,例如 Hbase,在 ES 中得到结果后再去 Hbase 查询这些字段。创建索引和查询时指定路由 Routing 值,这样可以精确到具体的分片查询,提升查询效率。路由的选择需要注意数据的分布均衡。JVM 调优JVM 调优建议如下:确保堆内存最小值( Xms )与最大值( Xmx )的大小是相同的,防止程序在运行时改变堆内存大小。Elasticsearch 默认安装后设置的堆内存是 1GB。可通过 ../config/jvm.option 文件进行配置,但是最好不要超过物理内存的50%和超过 32GB。GC 默认采用 CMS 的方式,并发但是有 STW 的问题,可以考虑使用 G1 收集器。ES 非常依赖文件系统缓存(Filesystem Cache),快速搜索。一般来说,应该至少确保物理上有一半的可用内存分配到文件系统缓存。来源:http://cnblogs.com/jajian/p/11223992.html编辑于 2022-04-11 22:51搜索引擎Elasticsearch程序员​赞同 84​​3 条评论​分享​喜欢​收藏​申请转载​文章被以下专栏收录炮哥和他的Java关注炮哥没什么值钱的东西,只有干巴巴的技术

什么是 Elasticsearch?一篇搞懂-腾讯云开发者社区-腾讯云

Elasticsearch?一篇搞懂-腾讯云开发者社区-腾讯云乔戈里什么是 Elasticsearch?一篇搞懂关注作者腾讯云开发者社区文档建议反馈控制台首页学习活动专区工具TVP最新优惠活动文章/答案/技术大牛搜索搜索关闭发布登录/注册首页学习活动专区工具TVP最新优惠活动返回腾讯云官网乔戈里首页学习活动专区工具TVP最新优惠活动返回腾讯云官网社区首页 >专栏 >什么是 Elasticsearch?一篇搞懂什么是 Elasticsearch?一篇搞懂乔戈里关注发布于 2020-02-14 12:31:4551.1K2发布于 2020-02-14 12:31:45举报文章被收录于专栏:Java那些事Java那些事前言不知道大家的公司用Elasticsearch多不多,反正我公司的是有在用的。平时听同事们聊天肯定避免不了不认识的技术栈,例如说:把数据放在引擎,从引擎取出数据等等。如果对引擎不了解的同学,就压根听不懂他们在说什么(我就是听不懂的一位,扎心了)。引擎一般指的是搜索引擎,现在用得比较多的就是Elasticsearch。这篇文章主要是对Elasticsearch一个简单的入门,没有高深的知识和使用。至少我想做到的是:以后同事们聊引擎了,至少知道他们在讲什么。什么是Elasticsearch?Elasticsearch is a real-time, distributed storage, search, and analytics engineElasticsearch 是一个实时的分布式存储、搜索、分析的引擎。介绍那儿有几个关键字:实时分布式搜索分析于是我们就得知道Elasticsearch是怎么做到实时的,Elasticsearch的架构是怎么样的(分布式)。存储、搜索和分析(得知道Elasticsearch是怎么存储、搜索和分析的)这些问题在这篇文章中都会有提及。

我已经写了200多篇原创技术文章了,后续会写大数据相关的文章,如果想看我其他文章的同学,不妨关注我吧。公众号:Java3y

如果觉得我这篇文章还不错,对你有帮助,不要吝啬自己的赞!为什么要用Elasticsearch在学习一项技术之前,必须先要了解为什么要使用这项技术。所以,为什么要使用Elasticsearch呢?我们在日常开发中,数据库也能做到(实时、存储、搜索、分析)。相对于数据库,Elasticsearch的强大之处就是可以模糊查询。有的同学可能就会说:我数据库怎么就不能模糊查询了??我反手就给你写一个SQL:select * from user where name like '%公众号Java3y%'

复制这不就可以把公众号Java3y相关的内容搜索出来了吗?的确,这样做的确可以。但是要明白的是:name like %Java3y%这类的查询是不走索引的,不走索引意味着:只要你的数据库的量很大(1亿条),你的查询肯定会是秒级别的如果对数据库索引还不是很了解的同学,建议复看一下我以前的文章。我觉得我当时写得还不赖(哈哈哈)

GitHub搜关键字:”索引“而且,即便给你从数据库根据模糊匹配查出相应的记录了,那往往会返回大量的数据给你,往往你需要的数据量并没有这么多,可能50条记录就足够了。还有一个就是:用户输入的内容往往并没有这么的精确,比如我从Google输入ElastcSeach(打错字),但是Google还是能估算我想输入的是Elasticsearch而Elasticsearch是专门做搜索的,就是为了解决上面所讲的问题而生的,换句话说:Elasticsearch对模糊搜索非常擅长(搜索速度很快)从Elasticsearch搜索到的数据可以根据评分过滤掉大部分的,只要返回评分高的给用户就好了(原生就支持排序)没有那么准确的关键字也能搜出相关的结果(能匹配有相关性的记录)下面我们就来学学为什么Elasticsearch可以做到上面的几点。Elasticsearch的数据结构众所周知,你要在查询的时候花得更少的时间,你就需要知道他的底层数据结构是怎么样的;举个例子:树型的查找时间复杂度一般是O(logn)链表的查找时间复杂度一般是O(n)哈希表的查找时间复杂度一般是O(1)….不同的数据结构所花的时间往往不一样,你想要查找的时候要快,就需要有底层的数据结构支持从上面说Elasticsearch的模糊查询速度很快,那Elasticsearch的底层数据结构是什么呢?我们来看看。我们根据“完整的条件”查找一条记录叫做正向索引;我们一本书的章节目录就是正向索引,通过章节名称就找到对应的页码。首先我们得知道为什么Elasticsearch为什么可以实现快速的“模糊匹配”/“相关性查询”,实际上是你写入数据到Elasticsearch的时候会进行分词。还是以上图为例,上图出现了4次“算法”这个词,我们能不能根据这次词为它找他对应的目录?Elasticsearch正是这样干的,如果我们根据上图来做这个事,会得到类似这样的结果:算法 ->2,13,42,56这代表着“算法”这个词肯定是在第二页、第十三页、第四十二页、第五十六页出现过。这种根据某个词(不完整的条件)再查找对应记录,叫做倒排索引。再看下面的图,好好体会一下:众所周知,世界上有这么多的语言,那Elasticsearch怎么切分这些词呢?,Elasticsearch内置了一些分词器Standard Analyzer 。按词切分,将词小写Simple Analyzer。按非字母过滤(符号被过滤掉),将词小写WhitespaceAnalyzer。按照空格切分,不转小写….等等等Elasticsearch分词器主要由三部分组成:???????Character Filters(文本过滤器,去除HTML)Tokenizer(按照规则切分,比如空格)TokenFilter(将切分后的词进行处理,比如转成小写)显然,Elasticsearch是老外写的,内置的分词器都是英文类的,而我们用户搜索的时候往往搜的是中文,现在中文分词器用得最多的就是IK。扯了一大堆,那Elasticsearch的数据结构是怎么样的呢?看下面的图:我们输入一段文字,Elasticsearch会根据分词器对我们的那段文字进行分词(也就是图上所看到的Ada/Allen/Sara..),这些分词汇总起来我们叫做Term Dictionary,而我们需要通过分词找到对应的记录,这些文档ID保存在PostingList在Term Dictionary中的词由于是非常非常多的,所以我们会为其进行排序,等要查找的时候就可以通过二分来查,不需要遍历整个Term Dictionary由于Term Dictionary的词实在太多了,不可能把Term Dictionary所有的词都放在内存中,于是Elasticsearch还抽了一层叫做Term Index,这层只存储 部分 词的前缀,Term Index会存在内存中(检索会特别快)Term Index在内存中是以FST(Finite State Transducers)的形式保存的,其特点是非常节省内存。FST有两个优点:1)空间占用小。通过对词典中单词前缀和后缀的重复利用,压缩了存储空间;2)查询速度快。O(len(str))的查询时间复杂度。前面讲到了Term Index是存储在内存中的,且Elasticsearch用FST(Finite State Transducers)的形式保存(节省内存空间)。Term Dictionary在Elasticsearch也是为他进行排序(查找的时候方便),其实PostingList也有对应的优化。PostingList会使用Frame Of Reference(FOR)编码技术对里边的数据进行压缩,节约磁盘空间。PostingList里边存的是文档ID,我们查的时候往往需要对这些文档ID做交集和并集的操作(比如在多条件查询时),PostingList使用Roaring Bitmaps来对文档ID进行交并集操作。使用Roaring Bitmaps的好处就是可以节省空间和快速得出交并集的结果。所以到这里我们总结一下Elasticsearch的数据结构有什么特点:Elasticsearch的术语和架构从官网的介绍我们已经知道Elasticsearch是分布式存储的,如果看过我的文章的同学,对分布式这个概念应该不陌生了。如果对分布式还不是很了解的同学,建议复看一下我以前的文章。我觉得我当时写得还不赖(哈哈哈)

GitHub搜关键字:

”SpringCloud“,"Zookeeper","Kafka","单点登录"在讲解Elasticsearch的架构之前,首先我们得了解一下Elasticsearch的一些常见术语。Index:Elasticsearch的Index相当于数据库的TableType:这个在新的Elasticsearch版本已经废除(在以前的Elasticsearch版本,一个Index下支持多个Type--有点类似于消息队列一个topic下多个group的概念)Document:Document相当于数据库的一行记录Field:相当于数据库的Column的概念Mapping:相当于数据库的Schema的概念DSL:相当于数据库的SQL(给我们读取Elasticsearch数据的API)相信大家看完上面的对比图,对Elasticsearch的一些术语就不难理解了。那Elasticsearch的架构是怎么样的呢?下面我们来看看:一个Elasticsearch集群会有多个Elasticsearch节点,所谓节点实际上就是运行着Elasticsearch进程的机器。在众多的节点中,其中会有一个Master Node,它主要负责维护索引元数据、负责切换主分片和副本分片身份等工作(后面会讲到分片的概念),如果主节点挂了,会选举出一个新的主节点。从上面我们也已经得知,Elasticsearch最外层的是Index(相当于数据库 表的概念);一个Index的数据我们可以分发到不同的Node上进行存储,这个操作就叫做分片。比如现在我集群里边有4个节点,我现在有一个Index,想将这个Index在4个节点上存储,那我们可以设置为4个分片。这4个分片的数据合起来就是Index的数据为什么要分片?原因也很简单:如果一个Index的数据量太大,只有一个分片,那只会在一个节点上存储,随着数据量的增长,一个节点未必能把一个Index存储下来。多个分片,在写入或查询的时候就可以并行操作(从各个节点中读写数据,提高吞吐量)现在问题来了,如果某个节点挂了,那部分数据就丢了吗?显然Elasticsearch也会想到这个问题,所以分片会有主分片和副本分片之分(为了实现高可用)数据写入的时候是写到主分片,副本分片会复制主分片的数据,读取的时候主分片和副本分片都可以读。Index需要分为多少个主分片和副本分片都是可以通过配置设置的如果某个节点挂了,前面所提高的Master Node就会把对应的副本分片提拔为主分片,这样即便节点挂了,数据就不会丢。到这里我们可以简单总结一下Elasticsearch的架构了:Elasticsearch 写入的流程上面我们已经知道当我们向Elasticsearch写入数据的时候,是写到主分片上的,我们可以了解更多的细节。客户端写入一条数据,到Elasticsearch集群里边就是由节点来处理这次请求:集群上的每个节点都是coordinating node(协调节点),协调节点表明这个节点可以做路由。比如节点1接收到了请求,但发现这个请求的数据应该是由节点2处理(因为主分片在节点2上),所以会把请求转发到节点2上。coodinate(协调)节点通过hash算法可以计算出是在哪个主分片上,然后路由到对应的节点shard = hash(document_id) % (num_of_primary_shards)路由到对应的节点以及对应的主分片时,会做以下的事:将数据写到内存缓存区然后将数据写到translog缓存区每隔1s数据从buffer中refresh到FileSystemCache中,生成segment文件,一旦生成segment文件,就能通过索引查询到了refresh完,memory buffer就清空了。每隔5s中,translog 从buffer flush到磁盘中定期/定量从FileSystemCache中,结合translog内容flush index到磁盘中。解释一下:Elasticsearch会把数据先写入内存缓冲区,然后每隔1s刷新到文件系统缓存区(当数据被刷新到文件系统缓冲区以后,数据才可以被检索到)。所以:Elasticsearch写入的数据需要1s才能查询到为了防止节点宕机,内存中的数据丢失,Elasticsearch会另写一份数据到日志文件上,但最开始的还是写到内存缓冲区,每隔5s才会将缓冲区的刷到磁盘中。所以:Elasticsearch某个节点如果挂了,可能会造成有5s的数据丢失。等到磁盘上的translog文件大到一定程度或者超过了30分钟,会触发commit操作,将内存中的segement文件异步刷到磁盘中,完成持久化操作。说白了就是:写内存缓冲区(定时去生成segement,生成translog),能够让数据能被索引、被持久化。最后通过commit完成一次的持久化。等主分片写完了以后,会将数据并行发送到副本集节点上,等到所有的节点写入成功就返回ack给协调节点,协调节点返回ack给客户端,完成一次的写入。Elasticsearch更新和删除Elasticsearch的更新和删除操作流程:给对应的doc记录打上.del标识,如果是删除操作就打上delete状态,如果是更新操作就把原来的doc标志为delete,然后重新新写入一条数据前面提到了,每隔1s会生成一个segement 文件,那segement文件会越来越多越来越多。Elasticsearch会有一个merge任务,会将多个segement文件合并成一个segement文件。在合并的过程中,会把带有delete状态的doc给物理删除掉。Elasticsearch查询查询我们最简单的方式可以分为两种:根据ID查询doc根据query(搜索词)去查询匹配的docpublic TopDocs search(Query query, int n);

public Document doc(int docID);

复制根据ID去查询具体的doc的流程是:检索内存的Translog文件检索硬盘的Translog文件检索硬盘的Segement文件根据query去匹配doc的流程是:同时去查询内存和硬盘的Segement文件从上面所讲的写入流程,我们就可以知道:Get(通过ID去查Doc是实时的),Query(通过query去匹配Doc是近实时的)因为segement文件是每隔一秒才生成一次的Elasticsearch查询又分可以为三个阶段:QUERY_AND_FETCH(查询完就返回整个Doc内容)QUERY_THEN_FETCH(先查询出对应的Doc id ,然后再根据Doc id 匹配去对应的文档)DFS_QUERY_THEN_FETCH(先算分,再查询)「这里的分指的是 词频率和文档的频率(Term Frequency、Document Frequency)众所周知,出现频率越高,相关性就更强」一般我们用得最多的就是QUERY_THEN_FETCH,第一种查询完就返回整个Doc内容(QUERY_AND_FETCH)只适合于只需要查一个分片的请求。QUERY_THEN_FETCH总体的流程流程大概是:客户端请求发送到集群的某个节点上。集群上的每个节点都是coordinate node(协调节点)然后协调节点将搜索的请求转发到所有分片上(主分片和副本分片都行)每个分片将自己搜索出的结果(doc id)返回给协调节点,由协调节点进行数据的合并、排序、分页等操作,产出最终结果。接着由协调节点根据 doc id 去各个节点上拉取实际的 document 数据,最终返回给客户端。Query Phase阶段时节点做的事:协调节点向目标分片发送查询的命令(转发请求到主分片或者副本分片上)数据节点(在每个分片内做过滤、排序等等操作),返回doc id给协调节点Fetch Phase阶段时节点做的是:协调节点得到数据节点返回的doc id,对这些doc id做聚合,然后将目标数据分片发送抓取命令(希望拿到整个Doc记录)数据节点按协调节点发送的doc id,拉取实际需要的数据返回给协调节点主流程我相信大家也不会太难理解,说白了就是:由于Elasticsearch是分布式的,所以需要从各个节点都拉取对应的数据,然后最终统一合成给客户端只是Elasticsearch把这些活都干了,我们在使用的时候无感知而已。本文参与 腾讯云自媒体分享计划,分享自微信公众号。原始发表:2020-01-17,如有侵权请联系 cloudcommunity@tencent.com 删除Elasticsearch Service数据库sql数据结构分布式本文分享自 程序员乔戈里 微信公众号,前往查看如有侵权,请联系 cloudcommunity@tencent.com 删除。本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!Elasticsearch Service数据库sql数据结构分布式评论登录后参与评论0 条评论热度最新登录 后参与评论推荐阅读LV.关注文章0获赞0目录什么是Elasticsearch?为什么要用ElasticsearchElasticsearch的数据结构Elasticsearch的术语和架构Elasticsearch 写入的流程Elasticsearch更新和删除Elasticsearch查询相关产品与服务Elasticsearch Service腾讯云 Elasticsearch Service(ES)是云端全托管海量数据检索分析服务,拥有高性能自研内核,集成X-Pack。ES 支持通过自治索引、存算分离、集群巡检等特性轻松管理集群,也支持免运维、自动弹性、按需使用的 Serverless 模式。使用 ES 您可以高效构建信息检索、日志分析、运维监控等服务,它独特的向量检索还可助您构建基于语义、图像的AI深度应用。免费体验产品介绍产品文档ES特惠专场,首月1折秒杀,新客首购6折起!

领券社区专栏文章阅读清单互动问答技术沙龙技术视频团队主页腾讯云TI平台活动自媒体分享计划邀请作者入驻自荐上首页技术竞赛资源技术周刊社区标签开发者手册开发者实验室关于社区规范免责声明联系我们友情链接腾讯云开发者扫码关注腾讯云开发者领取腾讯云代金券热门产品域名注册云服务器区块链服务消息队列网络加速云数据库域名解析云存储视频直播热门推荐人脸识别腾讯会议企业云CDN加速视频通话图像分析MySQL 数据库SSL 证书语音识别更多推荐数据安全负载均衡短信文字识别云点播商标注册小程序开发网站监控数据迁移Copyright © 2013 - 2024 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有 深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569腾讯云计算(北京)有限责任公司 京ICP证150476号 |  京ICP备11018762号 | 京公网安备号11010802020287问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档Copyright © 2013 - 2024 Tencent Cloud.All Rights Reserved. 腾讯云 版权所有登录 后参与评论200

Elasticsearch 平台 — 大规模查找实时答案 | Elastic

ticsearch 平台 — 大规模查找实时答案 | ElasticSkip to main contentPlatformPlatform解决方案解决方案客户客户资源资源定价定价文档文档Language pickerDeutschEnglishEspañolFrançais日本語한국어简体中文PortuguêsSearchLogin开始免费试用联系销售人员Elasticsearch Platform可观测性、安全和搜索等三大解决方案 — 由 Elasticsearch 平台提供支持。Elastic 概述ELK Stack搜索和分析、数据采集以及可视化,易如反掌KibanaElasticsearch集成ELK Stack 概述Elastic Cloud在您首选的云服务提供商平台上利用 Elastic 找到重要答案。Cloud 概述合作伙伴联系销售人员可观测性一体化实现应用和基础架构可见性,主动解决问题。日志监测应用程序性能监测基础架构监测合成监测真实用户监测Universal ProfilingAIOpsOpenTelemetry可观测性概述安全性快速、大规模地防范、调查和应对网络威胁。持续监测威胁猎捕调查和事件响应自动威胁防护安全性概述搜索在任何云中加速搜索结果,并提高个性化程度。生成式 AI搜索应用程序电子商务网站Workplace Search客户支持搜索概述按行业公共领域金融服务电信医疗保健技术零售和电子商务制造和汽车查看所有行业按解决方案让客户能够提升速度、灵活扩展并制定下一步的计划。可观测性安全性搜索客户聚焦了解 Cisco 如何借助 AI 打造搜索体验了解详情了解 RWE 如何为其可再生能源交易业务提供支持了解详情了解 Comcast 如何提高工程速度并加速创新了解详情开发人员深入了解与代码、论坛和群组相关的所有内容。社区论坛下载保持联系及时了解最新科技主题、创新技术和新闻。活动博文学习提高技能,开启未来成功之门。开始使用Elastic 资源咨询服务培训和认证安全实验室帮助无论是什么主题,都能找到所需的支持。联系我们支持中心了解 Elastic 的最新动态查看我们的演示库了解详情Elasticsearch 入门马上观看 Elastic 8.12 版的新功能了解详情SearchPlatformElasticsearch Platform可观测性、安全和搜索等三大解决方案 — 由 Elasticsearch 平台提供支持。Elastic 概述ELK Stack搜索和分析、数据采集以及可视化,易如反掌KibanaElasticsearch集成ELK Stack 概述Elastic Cloud在您首选的云服务提供商平台上利用 Elastic 找到重要答案。Cloud 概述合作伙伴联系销售人员解决方案可观测性一体化实现应用和基础架构可见性,主动解决问题。日志监测应用程序性能监测基础架构监测合成监测真实用户监测Universal ProfilingAIOpsOpenTelemetry可观测性概述安全性快速、大规模地防范、调查和应对网络威胁。持续监测威胁猎捕调查和事件响应自动威胁防护安全性概述搜索在任何云中加速搜索结果,并提高个性化程度。生成式 AI搜索应用程序电子商务网站Workplace Search客户支持搜索概述按行业公共领域金融服务电信医疗保健技术零售和电子商务制造和汽车查看所有行业客户按解决方案让客户能够提升速度、灵活扩展并制定下一步的计划。可观测性安全性搜索客户聚焦了解 Cisco 如何借助 AI 打造搜索体验了解详情了解 RWE 如何为其可再生能源交易业务提供支持了解详情了解 Comcast 如何提高工程速度并加速创新了解详情资源开发人员深入了解与代码、论坛和群组相关的所有内容。社区论坛下载保持联系及时了解最新科技主题、创新技术和新闻。活动博文学习提高技能,开启未来成功之门。开始使用Elastic 资源咨询服务培训和认证安全实验室帮助无论是什么主题,都能找到所需的支持。联系我们支持中心了解 Elastic 的最新动态查看我们的演示库了解详情Elasticsearch 入门马上观看 Elastic 8.12 版的新功能了解详情定价文档Language picker 语言DeutschEnglishEspañolFrançais日本語한국어简体中文PortuguêsLogin 登录开始免费试用联系销售人员利用 Elasticsearch 和 AI,更快地获得见解Elastic 让每个人都能够从所有数据中大规模、实时地找到重要答案。借助 AI 推动成果转化免费试用我们的客户将搜索应用到业务中查看所有成功案例基于 Elasticsearch 构建的三大解决方案通过由 Elasticsearch Platform 和 AI 提供支持的开放且灵活的企业解决方案,以前所未有的速度获得相关结果。您可以… 尽量减少中断时间。加速完成根本原因分析。大规模响应威胁。探索 Elasticsearch Platform可观测性利用先进的 ML 和分析技术,提供开放、灵活和一体化的可观测性,加快问题解决速度。可观测性概述安全性使用具有 SIEM、EDR 和云安全性的一体化解决方案,实现大规模地自动防范、调查和响应。安全性概述搜索为客户和员工构建由 AI 和 Machine Learning 提供强大支持的搜索应用程序。搜索概述想获得这样的结果?试试 Elastic 吧!10倍速度提升,价格仅为其他可观测性解决方案的一半62%整体风险大幅降低,有效阻止勒索软件和高级威胁查看 Elastic 能为您做的一切开始免费试用查看定价使用 Elasticsearch 和 ELK Stack 精简开发流程前往文档中心加入讨论试用加入我们的全球开发社区包括您在内的贡献者对 Elasticsearch 贡献颇多,代码工作只是一个方面。这是我们大家共同的社区。您可以提出问题、加入对话,并分享知识。联系我们探索可借助 Elastic 实现的各种体验随时了解 Elastic 的最新动态阅读新闻拓展您的专业知识了解活动与不断发展的社区保持同步查看博文准备好让数据发挥作用了吗?开始免费试用联系我们关注我们关于我们关于 Elastic发展历程领导团队DE&I博文加入我们招贤纳士招聘门户新闻稿新闻发布稿新闻文章合作伙伴寻找合作伙伴合作伙伴登录申请访问权限成为合作伙伴信任和安全性EthicsPoint 门户安全和隐私ECCN 报告道德准则邮件投资者关系投资者资源治理金融股票卓越奖往届获奖者ElasticON 之旅成为赞助商所有活动关于我们关于 Elastic发展历程领导团队DE&I博文加入我们招贤纳士招聘门户新闻稿新闻发布稿新闻文章合作伙伴寻找合作伙伴合作伙伴登录申请访问权限成为合作伙伴信任和安全性EthicsPoint 门户安全和隐私ECCN 报告道德准则邮件投资者关系投资者资源治理金融股票卓越奖往届获奖者ElasticON 之旅成为赞助商所有活动商标使用条款隐私网站地图© .Elasticsearch B.V.保留所有权利Elastic、Elasticsearch 及其他相关标志为 Elasticsearch B.V. 在美国和其他国家/地区的商标、徽标或注册商标。Apache、Apache Lucene、Apache Hadoop、Hadoop、HDFS 和黄色大象徽标是 Apache 软件基金会的注册商标,已在美国和/或其他国家/地区

全文搜索引擎 Elasticsearch 入门教程 - 阮一峰的网络日志

全文搜索引擎 Elasticsearch 入门教程 - 阮一峰的网络日志

阮一峰的网络日志 » 首页 » 档案

上一篇:Koa 框架教程   

下一篇:你的鞋都比你聪明   

分类:

开发者手册

⇐ 

 ⇒

全文搜索引擎 Elasticsearch 入门教程

作者: 阮一峰

日期: 2017年8月17日

全文搜索属于最常见的需求,开源的 Elasticsearch (以下简称 Elastic)是目前全文搜索引擎的首选。

它可以快速地储存、搜索和分析海量数据。维基百科、Stack Overflow、Github 都采用它。

Elastic 的底层是开源库 Lucene。但是,你没法直接用 Lucene,必须自己写代码去调用它的接口。Elastic 是 Lucene 的封装,提供了 REST API 的操作接口,开箱即用。

本文从零开始,讲解如何使用 Elastic 搭建自己的全文搜索引擎。每一步都有详细的说明,大家跟着做就能学会。

一、安装

Elastic 需要 Java 8 环境。如果你的机器还没安装 Java,可以参考这篇文章,注意要保证环境变量JAVA_HOME正确设置。

安装完 Java,就可以跟着官方文档安装 Elastic。直接下载压缩包比较简单。

$ wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.5.1.zip

$ unzip elasticsearch-5.5.1.zip

$ cd elasticsearch-5.5.1/

接着,进入解压后的目录,运行下面的命令,启动 Elastic。

$ ./bin/elasticsearch

如果这时报错"max virtual memory areas vm.maxmapcount [65530] is too low",要运行下面的命令。

$ sudo sysctl -w vm.max_map_count=262144

如果一切正常,Elastic 就会在默认的9200端口运行。这时,打开另一个命令行窗口,请求该端口,会得到说明信息。

$ curl localhost:9200

{

"name" : "atntrTf",

"cluster_name" : "elasticsearch",

"cluster_uuid" : "tf9250XhQ6ee4h7YI11anA",

"version" : {

"number" : "5.5.1",

"build_hash" : "19c13d0",

"build_date" : "2017-07-18T20:44:24.823Z",

"build_snapshot" : false,

"lucene_version" : "6.6.0"

},

"tagline" : "You Know, for Search"

}

上面代码中,请求9200端口,Elastic 返回一个 JSON 对象,包含当前节点、集群、版本等信息。

按下 Ctrl + C,Elastic 就会停止运行。

默认情况下,Elastic 只允许本机访问,如果需要远程访问,可以修改 Elastic 安装目录的config/elasticsearch.yml文件,去掉network.host的注释,将它的值改成0.0.0.0,然后重新启动 Elastic。

network.host: 0.0.0.0

上面代码中,设成0.0.0.0让任何人都可以访问。线上服务不要这样设置,要设成具体的 IP。

二、基本概念

2.1 Node 与 Cluster

Elastic 本质上是一个分布式数据库,允许多台服务器协同工作,每台服务器可以运行多个 Elastic 实例。

单个 Elastic 实例称为一个节点(node)。一组节点构成一个集群(cluster)。

2.2 Index

Elastic 会索引所有字段,经过处理后写入一个反向索引(Inverted Index)。查找数据的时候,直接查找该索引。

所以,Elastic 数据管理的顶层单位就叫做 Index(索引)。它是单个数据库的同义词。每个 Index (即数据库)的名字必须是小写。

下面的命令可以查看当前节点的所有 Index。

$ curl -X GET 'http://localhost:9200/_cat/indices?v'

2.3 Document

Index 里面单条的记录称为 Document(文档)。许多条 Document 构成了一个 Index。

Document 使用 JSON 格式表示,下面是一个例子。

{

"user": "张三",

"title": "工程师",

"desc": "数据库管理"

}

同一个 Index 里面的 Document,不要求有相同的结构(scheme),但是最好保持相同,这样有利于提高搜索效率。

2.4 Type

Document 可以分组,比如weather这个 Index 里面,可以按城市分组(北京和上海),也可以按气候分组(晴天和雨天)。这种分组就叫做 Type,它是虚拟的逻辑分组,用来过滤 Document。

不同的 Type 应该有相似的结构(schema),举例来说,id字段不能在这个组是字符串,在另一个组是数值。这是与关系型数据库的表的一个区别。性质完全不同的数据(比如products和logs)应该存成两个 Index,而不是一个 Index 里面的两个 Type(虽然可以做到)。

下面的命令可以列出每个 Index 所包含的 Type。

$ curl 'localhost:9200/_mapping?pretty=true'

根据规划,Elastic 6.x 版只允许每个 Index 包含一个 Type,7.x 版将会彻底移除 Type。

三、新建和删除 Index

新建 Index,可以直接向 Elastic 服务器发出 PUT 请求。下面的例子是新建一个名叫weather的 Index。

$ curl -X PUT 'localhost:9200/weather'

服务器返回一个 JSON 对象,里面的acknowledged字段表示操作成功。

{

"acknowledged":true,

"shards_acknowledged":true

}

然后,我们发出 DELETE 请求,删除这个 Index。

$ curl -X DELETE 'localhost:9200/weather'

四、中文分词设置

首先,安装中文分词插件。这里使用的是 ik,也可以考虑其他插件(比如 smartcn)。

$ ./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v5.5.1/elasticsearch-analysis-ik-5.5.1.zip

上面代码安装的是5.5.1版的插件,与 Elastic 5.5.1 配合使用。

接着,重新启动 Elastic,就会自动加载这个新安装的插件。

然后,新建一个 Index,指定需要分词的字段。这一步根据数据结构而异,下面的命令只针对本文。基本上,凡是需要搜索的中文字段,都要单独设置一下。

$ curl -X PUT 'localhost:9200/accounts' -d '

{

"mappings": {

"person": {

"properties": {

"user": {

"type": "text",

"analyzer": "ik_max_word",

"search_analyzer": "ik_max_word"

},

"title": {

"type": "text",

"analyzer": "ik_max_word",

"search_analyzer": "ik_max_word"

},

"desc": {

"type": "text",

"analyzer": "ik_max_word",

"search_analyzer": "ik_max_word"

}

}

}

}

}'

上面代码中,首先新建一个名称为accounts的 Index,里面有一个名称为person的 Type。person有三个字段。

user

title

desc

这三个字段都是中文,而且类型都是文本(text),所以需要指定中文分词器,不能使用默认的英文分词器。

Elastic 的分词器称为 analyzer。我们对每个字段指定分词器。

"user": {

"type": "text",

"analyzer": "ik_max_word",

"search_analyzer": "ik_max_word"

}

上面代码中,analyzer是字段文本的分词器,search_analyzer是搜索词的分词器。ik_max_word分词器是插件ik提供的,可以对文本进行最大数量的分词。

五、数据操作

5.1 新增记录

向指定的 /Index/Type 发送 PUT 请求,就可以在 Index 里面新增一条记录。比如,向/accounts/person发送请求,就可以新增一条人员记录。

$ curl -X PUT 'localhost:9200/accounts/person/1' -d '

{

"user": "张三",

"title": "工程师",

"desc": "数据库管理"

}'

服务器返回的 JSON 对象,会给出 Index、Type、Id、Version 等信息。

{

"_index":"accounts",

"_type":"person",

"_id":"1",

"_version":1,

"result":"created",

"_shards":{"total":2,"successful":1,"failed":0},

"created":true

}

如果你仔细看,会发现请求路径是/accounts/person/1,最后的1是该条记录的 Id。它不一定是数字,任意字符串(比如abc)都可以。

新增记录的时候,也可以不指定 Id,这时要改成 POST 请求。

$ curl -X POST 'localhost:9200/accounts/person' -d '

{

"user": "李四",

"title": "工程师",

"desc": "系统管理"

}'

上面代码中,向/accounts/person发出一个 POST 请求,添加一个记录。这时,服务器返回的 JSON 对象里面,_id字段就是一个随机字符串。

{

"_index":"accounts",

"_type":"person",

"_id":"AV3qGfrC6jMbsbXb6k1p",

"_version":1,

"result":"created",

"_shards":{"total":2,"successful":1,"failed":0},

"created":true

}

注意,如果没有先创建 Index(这个例子是accounts),直接执行上面的命令,Elastic 也不会报错,而是直接生成指定的 Index。所以,打字的时候要小心,不要写错 Index 的名称。

5.2 查看记录

向/Index/Type/Id发出 GET 请求,就可以查看这条记录。

$ curl 'localhost:9200/accounts/person/1?pretty=true'

上面代码请求查看/accounts/person/1这条记录,URL 的参数pretty=true表示以易读的格式返回。

返回的数据中,found字段表示查询成功,_source字段返回原始记录。

{

"_index" : "accounts",

"_type" : "person",

"_id" : "1",

"_version" : 1,

"found" : true,

"_source" : {

"user" : "张三",

"title" : "工程师",

"desc" : "数据库管理"

}

}

如果 Id 不正确,就查不到数据,found字段就是false。

$ curl 'localhost:9200/weather/beijing/abc?pretty=true'

{

"_index" : "accounts",

"_type" : "person",

"_id" : "abc",

"found" : false

}

5.3 删除记录

删除记录就是发出 DELETE 请求。

$ curl -X DELETE 'localhost:9200/accounts/person/1'

这里先不要删除这条记录,后面还要用到。

5.4 更新记录

更新记录就是使用 PUT 请求,重新发送一次数据。

$ curl -X PUT 'localhost:9200/accounts/person/1' -d '

{

"user" : "张三",

"title" : "工程师",

"desc" : "数据库管理,软件开发"

}'

{

"_index":"accounts",

"_type":"person",

"_id":"1",

"_version":2,

"result":"updated",

"_shards":{"total":2,"successful":1,"failed":0},

"created":false

}

上面代码中,我们将原始数据从"数据库管理"改成"数据库管理,软件开发"。 返回结果里面,有几个字段发生了变化。

"_version" : 2,

"result" : "updated",

"created" : false

可以看到,记录的 Id 没变,但是版本(version)从1变成2,操作类型(result)从created变成updated,created字段变成false,因为这次不是新建记录。

六、数据查询

6.1 返回所有记录

使用 GET 方法,直接请求/Index/Type/_search,就会返回所有记录。

$ curl 'localhost:9200/accounts/person/_search'

{

"took":2,

"timed_out":false,

"_shards":{"total":5,"successful":5,"failed":0},

"hits":{

"total":2,

"max_score":1.0,

"hits":[

{

"_index":"accounts",

"_type":"person",

"_id":"AV3qGfrC6jMbsbXb6k1p",

"_score":1.0,

"_source": {

"user": "李四",

"title": "工程师",

"desc": "系统管理"

}

},

{

"_index":"accounts",

"_type":"person",

"_id":"1",

"_score":1.0,

"_source": {

"user" : "张三",

"title" : "工程师",

"desc" : "数据库管理,软件开发"

}

}

]

}

}

上面代码中,返回结果的 took字段表示该操作的耗时(单位为毫秒),timed_out字段表示是否超时,hits字段表示命中的记录,里面子字段的含义如下。

total:返回记录数,本例是2条。

max_score:最高的匹配程度,本例是1.0。

hits:返回的记录组成的数组。

返回的记录中,每条记录都有一个_score字段,表示匹配的程序,默认是按照这个字段降序排列。

6.2 全文搜索

Elastic 的查询非常特别,使用自己的查询语法,要求 GET 请求带有数据体。

$ curl 'localhost:9200/accounts/person/_search' -d '

{

"query" : { "match" : { "desc" : "软件" }}

}'

上面代码使用 Match 查询,指定的匹配条件是desc字段里面包含"软件"这个词。返回结果如下。

{

"took":3,

"timed_out":false,

"_shards":{"total":5,"successful":5,"failed":0},

"hits":{

"total":1,

"max_score":0.28582606,

"hits":[

{

"_index":"accounts",

"_type":"person",

"_id":"1",

"_score":0.28582606,

"_source": {

"user" : "张三",

"title" : "工程师",

"desc" : "数据库管理,软件开发"

}

}

]

}

}

Elastic 默认一次返回10条结果,可以通过size字段改变这个设置。

$ curl 'localhost:9200/accounts/person/_search' -d '

{

"query" : { "match" : { "desc" : "管理" }},

"size": 1

}'

上面代码指定,每次只返回一条结果。

还可以通过from字段,指定位移。

$ curl 'localhost:9200/accounts/person/_search' -d '

{

"query" : { "match" : { "desc" : "管理" }},

"from": 1,

"size": 1

}'

上面代码指定,从位置1开始(默认是从位置0开始),只返回一条结果。

6.3 逻辑运算

如果有多个搜索关键字, Elastic 认为它们是or关系。

$ curl 'localhost:9200/accounts/person/_search' -d '

{

"query" : { "match" : { "desc" : "软件 系统" }}

}'

上面代码搜索的是软件 or 系统。

如果要执行多个关键词的and搜索,必须使用布尔查询。

$ curl 'localhost:9200/accounts/person/_search' -d '

{

"query": {

"bool": {

"must": [

{ "match": { "desc": "软件" } },

{ "match": { "desc": "系统" } }

]

}

}

}'

七、参考链接

ElasticSearch 官方手册

A Practical Introduction to Elasticsearch

(完)

文档信息

版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)

发表日期: 2017年8月17日

相关文章

2023.08.08: 《TypeScript 教程》发布了

长话短说,我写了一本《TypeScript 教程》,已经发布在网道,欢迎大家访问。

2023.03.21: 运维的未来是平台工程

互联网公司有一个重要工种,叫做"运维"。

2022.10.23: 最简单的 Git 服务器

程序员的代码仓库,总是需要托管一份在服务器,这样才保险,也方便使用。

2022.06.29: 云主机上手教程:轻量应用服务器体验

很多同学都希望架设自己的云服务,这就离不开云主机(cloud server)。

留言(95条)

Arther

说:

Java7也可以用。

2017年8月17日 08:08

| #

| 引用

Viky

说:

求协同工作的 FileBeat、Kibana 的教程,这样日志的收集过滤才算完整吧

2017年8月17日 08:45

| #

| 引用

antior

说:

这个软件,有什么用呢?

2017年8月17日 09:26

| #

| 引用

zhujun24

说:

ElasticSearch 可以做拼音搜索么?比如用 bianxingjingang 或者 bxjg 搜索到“变形金刚”。

2017年8月17日 09:46

| #

| 引用

jose

说:

调用过es的接口 蛮复杂的 改天实践一下

2017年8月17日 09:47

| #

| 引用

honpery

说:

觉得阮老师应该带头普及docker,docker注定是未来 - -

2017年8月17日 10:22

| #

| 引用

卫书有道

说:

太及时了~~~~~

2017年8月17日 11:22

| #

| 引用

kaopur

说:

不错,正需要...

2017年8月17日 11:28

| #

| 引用

古德

说:

跟mongodb在语法上有些像。。。。

2017年8月17日 12:56

| #

| 引用

xxxx

说:

引用zhujun24的发言:

ElasticSearch 可以做拼音搜索么?比如用 bianxingjingang 或者 bxjg 搜索到“变形金刚”。

肯定不可以,但是你可以增加一个字段表示啊。

比如说,中国, 你再用一个 zhongguo 字段 表示。

可以用自定义分词器,进行分词

搜索的时候,就可以 搜索出来 zg了。

2017年8月17日 12:59

| #

| 引用

Macdull

说:

ES可以做数据仓库吗,或者有类似的案例吗?

2017年8月17日 13:20

| #

| 引用

awen

说:

正好这两天再看相关内容,要是node平台相关介绍就更好了

2017年8月17日 16:01

| #

| 引用

CODE大全

说:

我的博客底层的搜索用的就是Lucene。Lucene非常强大,目前公司ELK平台用到了ElasticSearch,日数据量达到了10亿级以上。

2017年8月17日 16:02

| #

| 引用

业余草

说:

引用xxxx的发言:

肯定不可以,但是你可以增加一个字段表示啊。

比如说,中国,你再用一个 zhongguo 字段 表示。

可以用自定义分词器,进行分词

搜索的时候,就可以 搜索出来 zg了。

搜狗有专门的插件,可以将汉字拼音化,拼音汉字化。但是对于一些拼音相同的词汇就不好处理了。

例如:renming,中文有,任命,认命,人名等。

2017年8月17日 16:07

| #

| 引用

sojson

说:

Elasticsearch 说说我的感受吧,我13年开始用,到现在4个年头了,我基本上是去一家公司,我就会改变原有的搜索或者NOSQL数据存储,改成Elasticsearch 。 Elasticsearch 有着以下特点:

第一,更新迭代快,社区活跃。文档现在着实丰富(这是选型的第一要素)。

第二,从性能上来说,确实目前来说是首选。

第三,目前第三方组件越来越多,只有你想不到的。

... ...

小白(Java)可以看看这个博客,http://www.sojson.com/blog/81.html

Ctrl + F 实现站内搜索,包括近义词,比如搜索ES,内容会出现Elasticsearch和ES的内容。脚本=JS=Javascript

2017年8月18日 13:13

| #

| 引用

dreamer

说:

刚准备学一下ES,抱着碰一下运气的心态来看看这里有木有,哇,简直不要太开心。

2017年8月20日 12:25

| #

| 引用

刘同周

说:

在现在利用行业门槛、低级知识互相开LIVE骗钱的时代,阮神还坚持分享知识,自由传播,真是可贵。

2017年8月20日 13:29

| #

| 引用

zhujun24

说:

引用业余草的发言:

搜狗有专门的插件,可以将汉字拼音化,拼音汉字化。但是对于一些拼音相同的词汇就不好处理了。

例如:renming,中文有,任命,认命,人名等。

自己写过一个中文转拼音的工具,结合ES加正则应该可以实现拼音搜索+高亮显示关键词。

https://github.com/zhujun24/chinese-to-pinyin

2017年8月21日 09:30

| #

| 引用

苹果虫子

说:

引用xxxx的发言:

肯定不可以,但是你可以增加一个字段表示啊。

比如说,中国,你再用一个 zhongguo 字段 表示。

可以用自定义分词器,进行分词

搜索的时候,就可以 搜索出来 zg了。

有一个同义词管理, 把IK的词库中的词都加上拼音的同义词,

2017年8月22日 19:18

| #

| 引用

bayker

说:

引用xxxx的发言:

肯定不可以,但是你可以增加一个字段表示啊。

比如说,中国,你再用一个 zhongguo 字段 表示。

可以用自定义分词器,进行分词

搜索的时候,就可以 搜索出来 zg了。

安装ik 的拼音分词就可以了。

2017年8月28日 12:47

| #

| 引用

ejzhang

说:

ElasticSearch 权威指南(中文版)

https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html

2017年8月30日 08:02

| #

| 引用

GlacJAY

说:

查了下 curl 的手册,加上 -d 参数后就是 POST 请求了,不是 GET。

2017年9月 6日 09:08

| #

| 引用

柳汉涛

说:

更新数据有个 "_update" 命令

2017年9月 6日 12:46

| #

| 引用

泽云027

说:

引用GlacJAY的发言:

查了下 curl 的手册,加上 -d 参数后就是 POST 请求了,不是 GET。

ES文档中解释过这个问题。这里GET是ES里面的说法,表示是查询而非创建的“概念”;当ES的查询请求是通过json文档表达时,需要使用HTTP的POST来“实现”。

2017年9月29日 07:07

| #

| 引用

fafu

说:

引用zhujun24的发言:

ElasticSearch 可以做拼音搜索么?比如用 bianxingjingang 或者 bxjg 搜索到“变形金刚”。

可以

2017年10月 9日 11:24

| #

| 引用

qdice007

说:

"6.2 全文搜索"的上面一行,"表示匹配的程序" 是不是应该是 "表示匹配的程度"

2017年10月18日 13:34

| #

| 引用

Jayson

说:

引用xxxx的发言:

肯定不可以,但是你可以增加一个字段表示啊。

比如说,中国,你再用一个 zhongguo 字段 表示。

可以用自定义分词器,进行分词

搜索的时候,就可以 搜索出来 zg了。

本来就有拼音分词啊,为什么不能用拼音搜索,只要在建立索引分词的时候用拼音加中文分词包,检索的时候就可以拼音中文检索啊

2017年10月23日 13:24

| #

| 引用

jayson

说:

windows下用cmd运行curl的话 命令都不要带单引号就可以正常运行了

2017年10月31日 19:41

| #

| 引用

lance

说:

引用xxxx的发言:

肯定不可以,但是你可以增加一个字段表示啊。

比如说,中国,你再用一个 zhongguo 字段 表示。

可以用自定义分词器,进行分词

搜索的时候,就可以 搜索出来 zg了。

这世界有个东西叫拼音分词的插件

2017年11月 7日 15:49

| #

| 引用

rick.liu

说:

阮哥,很敬佩你的人生。不过关于ES 我几个问题要问一下:

index->type->document 首先我在没在目前的版本看到关于移除type的说明, 其次,官方自己人的index下也是创建了很多个type来管理不同的mapping。所以关于同一个index下多个type对应不同的mapping会影响会检索速度,这个是在哪里体现的?。其实我个也赞同 一个index一个type,但实际官方也没采用这种方式(除filebeat之外,filebeat把不同的日志收到同一个index下,type为doc).

2017年11月13日 19:27

| #

| 引用

刘奇

说:

阮哥你好,有个问题想请教您,项目中需要用到es来实现数据统计,现在有这样一个需求不知道该如何实现,查了一下资料,也没有看到好的解决办法

现在有这样一组数据

[

{userId:1, name: 'liu', createTime:'2017-9-16', investMount: 1000, sex: 1},

{userId:1, name: 'liu', createTime:'2017-9-16', investMount: 2000, sex: 1},

{userId:1, name: 'liu', createTime:'2017-9-16', investMount: 3000, sex: 1},

{userId:2, name: 'wang', createTime:'2017-10-1', investMount: 1500, sex: 0},

{userId:3, name: 'zhang', createTime:'2017-10-14', investMount: 1800, sex: 1},

{userId:4, name: 'zhao', createTime:'2017-10-17', investMount: 4000, sex: 1}

]

比如:现在想查询注册时间(createTime)是2017-9-15到2017-10-15日之间,投资总额(同一个userId用户investMount的总和)在2000-5000之间的男性(sex==1)的用户,最后取到符合条件的userId的集合,这种需求该如何写DSL语句呢?

我现在对es的学习能力只能想到这一步,先根据固定的条件进行查询筛选,然后再根据用户id进行分组,查询每个用户的投资总金额,但是如何使最后结果能返回符合所有条件的用户userId的集合我还是想不出来,求指教~~

{

"query": {

"bool": {

"must": {

{"term": {"sex": 1}}

},

"filter": {

"range": {

"createTime": {

"from": "2017-9-15",

"to": "2017-10-15"

}

}

}

}

},

"aggs": {

"group_by_userId": {

"terms": {"field": "userId"},

"aggs": {

"sum_investMount": {

"sum": { "field": "investMount"}

}

}

}

}

}

2017年11月15日 21:36

| #

| 引用

Mr.J

说:

@刘奇:

三个条件,一个是时间条件,一个是性别,一个是投资额度区间对吧?你可以使用布尔查询的and将时间和性别过符合条件的先过滤出来,然后用聚合查询根据userid分组就可以了。或者使用嵌套桶的概念,也就是你说的分组,嵌套分组,每个条件分一个组。但是感觉先用过滤的话从逻辑和性能都会好点。哦,对了,如果你想返回的数据只有userID,可以使用top_hits,_source字段来控制返回的内容。我也是刚学,说的可能不对。

2017年11月20日 14:46

| #

| 引用

Salamander

说:

现在比较好的ES从MySQl同步数据的工具是什么?https://github.com/jprante/elasticsearch-jdbc 这个库都好久不更新了

2017年12月 7日 16:28

| #

| 引用

陈卓

说:

多亏阮神!原本以为es是冷门项目,没想到大神也在用。涉猎广泛啊!学习了

2017年12月18日 15:37

| #

| 引用

xiakejie

说:

2018第一签,还好评论不多,认真看完.

2018年1月 3日 21:54

| #

| 引用

高振波

说:

新建Index时按照官网的例子就会返回

{"error":"Content-Type header [application/x-www-form-urlencoded] is not supported","status":406}%

查了一下需要添加头文件请求 : -H "Content-Type: application/json"

2018年1月24日 17:13

| #

| 引用

DD

说:

大神们知道怎么新开一个节点嘛。按照教程本人启动了es照理说是一个节点,现在想再启动一个,是直接开个新的cmd然后bin里把es再跑一遍吗?

2018年1月25日 14:09

| #

| 引用

lancelot

说:

windows 用curl时,除了省略所有的单引号外需要注意外,-d 后的{"name":"zhu"}要改为{\"name\":\"zhu\"}

2018年1月30日 16:21

| #

| 引用

李朋印

说:

阮哥你好,我想请教下,类似mysql的like查询时,会默认将要搜索的字符串进行分词分析,,如果我不想分词分析,直接搜索,,,是不是只能修改es里面字段为未分析的? 是否会有相应的查询方式可以实现??谢谢了

2018年3月 7日 11:53

| #

| 引用

dingjie

说:

我在mac 里面执行了你上面的例子报错,麻烦你有时间看看

curl -X PUT 'localhost:9200/accounts' -d '

{

"mappings": {

"person": {

"properties": {

"user": {

"type": "text",

"analyzer": "ik_max_word",

"search_analyzer": "ik_max_word"

},

"title": {

"type": "text",

"analyzer": "ik_max_word",

"search_analyzer": "ik_max_word"

},

"desc": {

"type": "text",

"analyzer": "ik_max_word",

"search_analyzer": "ik_max_word"

}

}

}

}

}'

{"error":"Content-Type header [application/x-www-form-urlencoded] is not supported","status":406}%

2018年3月19日 18:51

| #

| 引用

dignjie

说:

我解决了上面的问题但是又报了curl -H "Content-Type: application/json" -X PUT 'localhost:9200/accounts' -d '{"mappings":{"person":{"properties":{"user":{"type":"text","analyzer":"ik_max_word","search_analyzer":"ik_max_word"},"title":{"type":"text","analyzer":"ik_max_word","search_analyzer":"ik_max_word"},"desc":{"type":"text","analyzer":"ik_max_word","search_analyzer":"ik_max_word"}}}}}'

{"error":{"root_cause":[{"type":"mapper_parsing_exception","reason":"analyzer [ik_max_word] not found for field [title]"}],"type":"mapper_parsing_exception","reason":"Failed to parse mapping [person]: analyzer [ik_max_word] not found for field [title]","caused_by":{"type":"mapper_parsing_exception","reason":"analyzer [ik_max_word] not found for field [title]"}},"status":400}%这个

2018年3月19日 19:15

| #

| 引用

dignjie

说:

不好意思, 原来是我安装了ki没有重启

2018年3月19日 19:29

| #

| 引用

test

说:

“如果要执行多个关键词的and搜索,必须使用布尔查询。”

可以用以下方式:

"match" : {

"message" : {

"query" : "this is a test",

"operator" : "and"

}

}

2018年3月22日 14:36

| #

| 引用

陈学礼

说:

路途坎坷,看楼主这篇文章我要先去安装VM虚拟机,然后在虚拟机中安装linux系统,然后还要安装jdk,然后才能安装楼主的elasticsearch,这中间遇到很多问题,还好都被解决了,总算把楼主的教程看完,谢谢楼主,如果楼主还有精力,希望顺便讲解一下Spring boot + elasticsearch + mysql的用法,综合在实际操作中的步骤,谢谢楼主,楼主辛苦了

2018年3月23日 17:10

| #

| 引用

虎口脱险

说:

引用陈学礼的发言:

路途坎坷,看楼主这篇文章我要先去安装VM虚拟机,然后在虚拟机中安装linux系统,然后还要安装jdk,然后才能安装楼主的elasticsearch,这中间遇到很多问题,还好都被解决了,总算把楼主的教程看完,谢谢楼主,如果楼主还有精力,希望顺便讲解一下Spring boot + elasticsearch + mysql的用法,综合在实际操作中的步骤,谢谢楼主,楼主辛苦了

为什么这些东西需要楼主去讲,而不是试着自己去实践

2018年4月 2日 10:17

| #

| 引用

茄盒

说:

学习中, `docker` 里还好自带有 `image`, 不过这下载速度也是要了命了,加了国内镜像也没啥用

2018年4月 9日 17:17

| #

| 引用

小陈

说:

通俗易懂,峰哥出手果然不一样

2018年4月26日 15:15

| #

| 引用

bog.king

说:

那是不是说,适合用eleatic做站内搜索引擎?

2018年5月11日 15:58

| #

| 引用

说:

引用陈学礼的发言:

路途坎坷,看楼主这篇文章我要先去安装VM虚拟机,然后在虚拟机中安装linux系统,然后还要安装jdk,然后才能安装楼主的elasticsearch,这中间遇到很多问题,还好都被解决了,总算把楼主的教程看完,谢谢楼主,如果楼主还有精力,希望顺便讲解一下Spring boot + elasticsearch + mysql的用法,综合在实际操作中的步骤,谢谢楼主,楼主辛苦了

只是学一下你完全可以安windows版啊

2018年5月11日 16:17

| #

| 引用

Jeffy

说:

http://localhost:9200/accounts/person/_search/

get:"max_score": 1,

post:"max_score": 0.25316024

为啥会这样呢?获取应该是get呀

2018年6月22日 16:04

| #

| 引用

yanbin

说:

你好,我是一个技术小白,老板目前要求我把公司wiki的搜索引擎改成es。请问这个任务具有可行操作性吗?如果可以的话,请问从零开始学习操作需要大概多长时间来完成呀?

2018年7月 3日 11:46

| #

| 引用

whforever

说:

讲的很清晰,解决了搞了半天的问题

2018年7月11日 19:38

| #

| 引用

震灵

说:

搜索貌似应该是发POST请求吧?

2018年7月14日 14:36

| #

| 引用

小罗

说:

新版页面看不到代码块,360浏览器

2018年7月19日 15:25

| #

| 引用

omgzui

说:

由于老师使用的是5.5.1,新版的6.3.1会报错{"error":"Content-Type header [application/x-www-form-urlencoded] is not supported","status":406}

解决办法:在每个请求上加上-H 'Content-Type:application/json'即可

2018年7月22日 11:45

| #

| 引用

helloworld

说:

阮神的分享精神真的值的点赞! 佩服

2018年7月27日 14:13

| #

| 引用

王业鑫

说:

此文章通俗易懂,但是知识建立在使用的基础上,没有针对集群等做深入的分析

2018年8月13日 11:29

| #

| 引用

hemingway

说:

照着你的例子练习了一遍,谢谢阮大神。

2018年8月17日 19:41

| #

| 引用

梦飞扬

说:

一启动就被killed了, 查了下是内存的问题, 但是怎么解决呢? 求指导

2018年8月24日 20:35

| #

| 引用

德金

说:

大神厉害,非常感谢,果断用起来

2018年8月28日 17:01

| #

| 引用

糖太粽

说:

谢谢阮神 目前在学习

2018年9月20日 14:47

| #

| 引用

青城之树

说:

感谢 条件检索用post

2018年10月15日 16:53

| #

| 引用

xhigeneral

说:

引用Jeffy的发言:

http://localhost:9200/accounts/person/_search/

get:"max_score": 1,

post:"max_score": 0.25316024

为啥会这样呢?获取应该是get呀

elastic的get常常都会带body的json,而post也是可以访问的。

2018年11月21日 23:17

| #

| 引用

FrozenSt

说:

引用陈学礼的发言:

路途坎坷,看楼主这篇文章我要先去安装VM虚拟机,然后在虚拟机中安装linux系统,然后还要安装jdk,然后才能安装楼主的elasticsearch,这中间遇到很多问题,还好都被解决了,总算把楼主的教程看完,谢谢楼主,如果楼主还有精力,希望顺便讲解一下Spring boot + elasticsearch + mysql的用法,综合在实际操作中的步骤,谢谢楼主,楼主辛苦了

您要的这些,一本书可都讲不完。

饭还是要一口一口吃。直接吃第三碗饭是吃不饱的。

2018年12月 5日 16:17

| #

| 引用

袖长风

说:

我安装了elasticsearch-6.5.4 和 analysis-ik 6.5.4;

重启:可以看到 ik plugin被加载

[2019-01-08T17:25:10,333][INFO ][o.e.p.PluginsService ] [00eqG7f] loaded plugin [analysis-ik]

然后测试:

curl -XGET "http://localhost:9200/index/_analyze?pretty" -H 'Content-Type: application/json' -d'

{

"text":"中华人民共和国MN","tokenizer": "ik_max_word"

}'

能够正常分词;

但是!建立索引,设置mapping的时候出错了

测试:

curl -XPUT http://localhost:9200/index

curl -XPOST http://localhost:9200/index/fulltext/_mapping?pretty -H 'Content-Type:application/json' -d'

{

"properties": {

"content": {

"type": "text",

"analyzer": "ik_max_word",

"search_analyzer": "ik_max_word"

}

}

}'

结果

{

"error" : {

"root_cause" : [

{

"type" : "mapper_parsing_exception",

"reason" : "analyzer [ik_max_word] not found for field [content]"

}

],

"type" : "mapper_parsing_exception",

"reason" : "analyzer [ik_max_word] not found for field [content]"

},

"status" : 400

}

为什么找不到分词器呢?都折磨我两天了...

2019年1月 8日 18:29

| #

| 引用

艾郦湾

说:

目前只有三万的数据 想通过elasticsearch做搜索 但是三万的数据在mysql里 这里只是讲解了增删改查 具体怎么样吧三万的数据能够快速的转移到elasticsearch上呢?

2019年1月16日 18:13

| #

| 引用

互联网非法移民

说:

@zhujun24 multi_field+拼音analyzer就可以实现

2019年1月24日 05:38

| #

| 引用

mrs.utopian

说:

୧(๑•̀◡•́๑)૭,很好写得,通俗易懂最难得!

2019年2月15日 16:40

| #

| 引用

晓晓

说:

引用zhujun24的发言:

ElasticSearch 可以做拼音搜索么?比如用 bianxingjingang 或者 bxjg 搜索到“变形金刚”。

可以的,但是需要安装插件

具体你可以看下这个项目,https://github.com/medcl/elasticsearch-analysis-pinyin

但是已经有一段时间没更新了

2019年2月28日 10:21

| #

| 引用

leefyi

说:

照着基础来了一遍。除去版本更新了以外,其它都差不多。 也算 体验了下~ 谢谢 阮大

2019年3月 3日 21:44

| #

| 引用

高飞

说:

引用陈学礼的发言:

路途坎坷,看楼主这篇文章我要先去安装VM虚拟机,然后在虚拟机中安装linux系统,然后还要安装jdk,然后才能安装楼主的elasticsearch,这中间遇到很多问题,还好都被解决了,总算把楼主的教程看完,谢谢楼主,如果楼主还有精力,希望顺便讲解一下Spring boot + elasticsearch + mysql的用法,综合在实际操作中的步骤,谢谢楼主,楼主辛苦了

可以看官方的docker版安装啊, 简单的让你想哭... https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html

2019年3月11日 16:17

| #

| 引用

efasscaed

说:

增加中文分词插件应当是如下配置文件

./bin/plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v5.5.1/elasticsearch-analysis-ik-5.5.1.zip

2019年3月15日 15:14

| #

| 引用

鄉民

说:

寫得真好, 一看就明白了

2019年3月21日 17:13

| #

| 引用

小恩

说:

最好的入门文档,没有之一

2019年3月28日 02:05

| #

| 引用

小白菜不菜

说:

引用omgzui的发言:

由于老师使用的是5.5.1,新版的6.3.1会报错{"error":"Content-Type header [application/x-www-form-urlencoded] is not supported","status":406}

解决办法:在每个请求上加上-H 'Content-Type:application/json'即可

没错,在6.0版本之后,请求都需要加 -H 'Content-Type:application/json'

2019年4月 8日 17:30

| #

| 引用

张小智

说:

提交问题

要让所有人访问是给配置文件加http.host为0.0.0.0 而不是改默认的network.host为0.0.0.0

2019年4月24日 08:15

| #

| 引用

eaglex

说:

通俗易懂,适合入门,非常感谢

2019年5月 9日 16:08

| #

| 引用

mrs.utopian

说:

获益良多

2019年5月13日 16:40

| #

| 引用

mrzhouxiaofei

说:

阮老师,你好,2.3 Document 部分,「 不要求有相同的结构(scheme)」 中 scheme 疑为 schema?

2019年8月26日 21:07

| #

| 引用

Spounds

说:

部署好es搜索之后,建立了索引,我输入'NSK 7028',和 'NSK 702',理论上,我搜索后面这一个关键字的时候,应该能带出前面这个关键字的输出结果吧?但是没有搜索出来,不知道为啥。有人能帮忙解答一下吗?

2019年9月19日 10:47

| #

| 引用

雨雨

说:

引用兰的发言:

docker 了解下~

jdk都不用你装~

只是学一下你完全可以安windows版啊

2020年4月22日 22:26

| #

| 引用

wwwd

说:

很棒

2020年4月23日 22:46

| #

| 引用

jack

说:

“上面代码中,设成0.0.0.0让任何人都可以访问”

这个说法是不正确的,通过任何网卡接口访问和任何人访问是两个概念。

2020年6月26日 12:13

| #

| 引用

陈孔璋

说:

引用zhujun24的发言:

ElasticSearch 可以做拼音搜索么?比如用 bianxingjingang 或者 bxjg 搜索到“变形金刚”。

可以,下载第三方分词器pinyin

2020年7月 2日 09:55

| #

| 引用

rick

说:

跟mysql数据库同步用什么工具?

2020年8月19日 10:33

| #

| 引用

aiteemo

说:

引用古德的发言:

跟mongodb在语法上有些像。。。。

可以的,有同义词扩展,需要维护

2020年8月24日 17:47

| #

| 引用

saven

说:

我这里有一个需求,就是需要将关系型数据库(国产数据库)的数据抽取到elasticsearch。除了通过写code从关系型数据库查出来再导入es中,有没有什么更好,或者说更高效的方法去实现数据的导入。

logstash我试过了,但是只能提前预定好sql语句即知道要查什么。并且只能初始化同步一次,然后根据配置的定时去抽取

我的业务场景中,sql是service code中动态生成的,所以要查询的数据也不确定。并需要可以手动触发进行增量/全量抽取。请问这该如何实现,各位前辈指点指点。

2020年8月25日 11:39

| #

| 引用

杨稳

说:

服务器端5.4.3,写客户端使用RestHighLevelClient5.6.0,当服务端因为另外的读客户端导致查询压力比较大时,写客户端有时会卡死,应该是Apache的httpasyncclient中的连接未释放,导致请求全部在连接队列里面,恢复不了,只能重启。测试环境无法复现。这个有遇到过吗?

2020年11月23日 17:30

| #

| 引用

海浪

说:

感谢阮老师的分享, 点赞

2021年4月 1日 16:41

| #

| 引用

helloworldの神

说:

中文分词设置要这么写才不出错,查了好久哈哈,不过我是在win系统上用postman试的

{

"mappings": {

"properties": {

"user": {

"type": "text",

"analyzer": "ik_max_word",

"search_analyzer": "ik_max_word"

},

"title": {

"type": "text",

"analyzer": "ik_max_word",

"search_analyzer": "ik_max_word"

},

"desc": {

"type": "text",

"analyzer": "ik_max_word",

"search_analyzer": "ik_max_word"

}

}

}

}

2021年4月15日 16:56

| #

| 引用

helloworldの神

说:

7.12新增数据地址要这么写,注意这个_doc

localhost:9200/accounts/_doc/1

2021年4月16日 10:23

| #

| 引用

yushijie

说:

5.1 新增记录

向指定的 /Index/Type 发送 PUT 请求;

此处应该是post请求

2021年6月 9日 14:35

| #

| 引用

mqray

说:

引用刘同周的发言:

在现在利用行业门槛、低级知识互相开LIVE骗钱的时代,阮神还坚持分享知识,自由传播,真是可贵。

早在4年前就看穿本质 厉害

2021年7月10日 11:14

| #

| 引用

贤大

说:

引用zhujun24的发言:

ElasticSearch 可以做拼音搜索么?比如用 bianxingjingang 或者 bxjg 搜索到“变形金刚”。

把文章弄成拼音,再加到索引中,这样中不

2021年8月20日 18:59

| #

| 引用

jtt

说:

引用zhujun24的发言:

ElasticSearch 可以做拼音搜索么?比如用 bianxingjingang 或者 bxjg 搜索到“变形金刚”。

可以啊,elastic支持同义词搜索,仅需要在安装目录config下配置同义词词典,在xml中配置同义词词典生效就行了

2021年12月28日 18:02

| #

| 引用

我要发表看法

您的留言

(HTML标签部分可用)

您的大名:

«-必填

电子邮件:

«-必填,不公开

个人网址:

«-我信任你,不会填写广告链接

记住个人信息?

正在发表您的评论,请稍候

«- 点击按钮

Weibo |

Twitter |

GitHub

Email: [email protected]

ElasticSearch (ES从入门到精通一篇就够了) - 不吃紫菜 - 博客园

ElasticSearch (ES从入门到精通一篇就够了) - 不吃紫菜 - 博客园

会员

周边

新闻

博问

AI培训

云市场

所有博客

当前博客

我的博客

我的园子

账号设置

简洁模式 ...

退出登录

注册

登录

不吃紫菜

学代码:得先会用——再横纵向比对别的方式——探究原因(分析源码)

博客园

首页

新随笔

联系

订阅

管理

ElasticSearch (ES从入门到精通一篇就够了)

Elasticsearch是位于 Elastic Stack 核心的分布式搜索和分析引擎。Elasticsearch 是索引、搜索和分析魔法发生的地方。lasticsearch 为所有类型的数据提供近乎实时的搜索和分析。无论您拥有结构化或非结构化文本、数字数据还是地理空间数据,Elasticsearch 都能以支持快速搜索的方式高效地存储和索引它。您可以超越简单的数据检索和聚合信息来发现数据中的趋势和模式。随着您的数据和查询量的增长,Elasticsearch 的分布式特性使您的部署能够随之无缝增长。

ES分布式搜索引擎

注意: 在没有创建库的时候搜索,ES会创建一个库并自动创建该字段并且设置为String类型也就是text

什么是elasticsearch?

一个开源的分布式搜索引擎,可以用来实现搜索、日志统计、分析、系统监控等功能

什么是elastic stack(ELK)?

是以elasticsearch为核心的技术栈,包括beats、Logstash、kibana、elasticsearch

什么是Lucene?

是Apache的开源搜索引擎类库,提供了搜索引擎的核心API

elasticsearch是一款非常强大的开源搜索引擎,具备非常多强大功能,可以帮助我们从海量数据中快速找到需要的内容

ELK技术栈

本文只使用了elasticsearch,以及kibana做可视化界面

elasticsearch结合kibana、Logstash、Beats,也就是elastic stack(ELK)。被广泛应用在日志数据分析、实时监控等领域:

而elasticsearch是elastic stack的核心,负责存储、搜索、分析数据。

初识elasticsearch

1. elasticsearch背景介绍

elasticsearch底层是基于lucene来实现的。

Lucene是一个Java语言的搜索引擎类库,是Apache公司的顶级项目,由DougCutting于1999年研发。官网地址:https://lucene.apache.org/ 。

elasticsearch的发展历史:

2004年Shay Banon基于Lucene开发了Compass

2010年Shay Banon 重写了Compass,取名为Elasticsearch。

2. 倒排索引

倒排索引的概念是基于MySQL这样的正向索引而言的。

2.1 正向索引

设置了索引的话挺快的,但要是模糊查询则就很慢!

那么什么是正向索引呢?例如给下表(tb_goods)中的id创建索引:

如果是根据id查询,那么直接走索引,查询速度非常快。

但如果是基于title做模糊查询,只能是逐行扫描数据,流程如下:

1)用户搜索数据,条件是title符合"%手机%"

2)逐行获取数据,比如id为1的数据

3)判断数据中的title是否符合用户搜索条件

4)如果符合则放入结果集,不符合则丢弃。回到步骤1

逐行扫描,也就是全表扫描,随着数据量增加,其查询效率也会越来越低。当数据量达到数百万时,就是一场灾难。

2.2 倒排索引

倒排索引中有两个非常重要的概念:

文档(Document):用来搜索的数据,其中的每一条数据就是一个文档。例如一个网页、一个商品信息

词条(Term):对文档数据或用户搜索数据,利用某种算法分词,得到的具备含义的词语就是词条。例如:我是中国人,就可以分为:我、是、中国人、中国、国人这样的几个词条

创建倒排索引是对正向索引的一种特殊处理,流程如下:

将每一个文档的数据利用算法分词,得到一个个词条

创建表,每行数据包括词条、词条所在文档id、位置等信息

因为词条唯一性,可以给词条创建索引,例如hash表结构索引

如图:

倒排索引的搜索流程如下(以搜索"华为手机"为例):

1)用户输入条件"华为手机"进行搜索。

2)对用户输入内容分词,得到词条:华为、手机。

3)拿着词条在倒排索引中查找,可以得到包含词条的文档id:1、2、3。

4)拿着文档id到正向索引中查找具体文档。

如图:

虽然要先查询倒排索引,再查询倒排索引,但是无论是词条、还是文档id都建立了索引,查询速度非常快!无需全表扫描。

2.3 正向和倒排对比

概念区别:

正向索引是最传统的,根据id索引的方式。但根据词条查询时,必须先逐条获取每个文档,然后判断文档中是否包含所需要的词条,是根据文档找词条的过程。

而倒排索引则相反,是先找到用户要搜索的词条,根据词条得到保护词条的文档的id,然后根据id获取文档。是根据词条找文档的过程。

优缺点:

正向索引:

优点:

可以给多个字段创建索引

根据索引字段搜索、排序速度非常快

缺点:

根据非索引字段,或者索引字段中的部分词条查找时,只能全表扫描。

倒排索引:

优点:

根据词条搜索、模糊搜索时,速度非常快

缺点:

只能给词条创建索引,而不是字段

无法根据字段做排序

3. ES数据库基本概念

elasticsearch中有很多独有的概念,与mysql中略有差别,但也有相似之处。

3.1.文档和字段

一个文档就像数据库里的一条数据,字段就像数据库里的列

elasticsearch是面向文档(Document)存储的,可以是数据库中的一条商品数据,一个订单信息。文档数据会被序列化为json格式后存储在elasticsearch中:

而Json文档中往往包含很多的字段(Field),类似于mysql数据库中的列。

3.2.索引和映射

索引就像数据库里的表,映射就像数据库中定义的表结构

索引(Index),就是相同类型的文档的集合【类似mysql中的表】

例如:

所有用户文档,就可以组织在一起,称为用户的索引;

所有商品的文档,可以组织在一起,称为商品的索引;

所有订单的文档,可以组织在一起,称为订单的索引;

因此,我们可以把索引当做是数据库中的表。

数据库的表会有约束信息,用来定义表的结构、字段的名称、类型等信息。因此,索引库中就有映射(mapping),是索引中文档的字段约束信息,类似表的结构约束。

3.3.mysql与elasticsearch

各自长处:

Mysql:擅长事务类型操作,可以确保数据的安全和一致性

Elasticsearch:擅长海量数据的搜索、分析、计算

我们统一的把mysql与elasticsearch的概念做一下对比:

MySQL

Elasticsearch

说明

Table

Index

索引(index),就是文档的集合,类似数据库的表(table)

Row

Document

文档(Document),就是一条条的数据,类似数据库中的行(Row),文档都是JSON格式

Column

Field

字段(Field),就是JSON文档中的字段,类似数据库中的列(Column)

Schema

Mapping

Mapping(映射)是索引中文档的约束,例如字段类型约束。类似数据库的表结构(Schema)

SQL

DSL

DSL是elasticsearch提供的JSON风格的请求语句,用来操作elasticsearch,实现CRUD

在企业中,往往是两者结合使用:

对安全性要求较高的写操作,使用mysql实现

对查询性能要求较高的搜索需求,使用elasticsearch实现

两者再基于某种方式,实现数据的同步,保证一致性

4. 安装es、kibana、分词器

分词器的作用是什么?

创建倒排索引时对文档分词

用户搜索时,对输入的内容分词

IK分词器有几种模式?

ik_smart:智能切分,粗粒度

ik_max_word:最细切分,细粒度

IK分词器如何拓展词条?如何停用词条?

利用config目录的IkAnalyzer.cfg.xml文件添加拓展词典和停用词典

在词典中添加拓展词条或者停用词条

4.1 部署单点es

4.1.1.创建网络

因为我们还需要部署kibana容器,因此需要让es和kibana容器互联。这里先创建一个网络:

docker network create es-net

4.1.2.加载镜像

这里我们采用elasticsearch的7.12.1版本的镜像,这个镜像体积非常大,接近1G。不建议大家自己pull。

课前资料提供了镜像的tar包:

大家将其上传到虚拟机中,然后运行命令加载即可:

# 导入数据

docker load -i es.tar

注意:同理还有kibana的tar包也需要这样做。

4.1.3.运行

运行docker命令,部署单点es:

docker run -d \

--name es \

-e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \

-e "discovery.type=single-node" \

-v es-data:/usr/share/elasticsearch/data \

-v es-plugins:/usr/share/elasticsearch/plugins \

--privileged \

--network es-net \

-p 9200:9200 \

-p 9300:9300 \

elasticsearch:7.12.1

命令解释:

-e "cluster.name=es-docker-cluster":设置集群名称

-e "http.host=0.0.0.0":监听的地址,可以外网访问

-e "ES_JAVA_OPTS=-Xms512m -Xmx512m":内存大小

-e "discovery.type=single-node":非集群模式

-v es-data:/usr/share/elasticsearch/data:挂载逻辑卷,绑定es的数据目录

-v es-logs:/usr/share/elasticsearch/logs:挂载逻辑卷,绑定es的日志目录

-v es-plugins:/usr/share/elasticsearch/plugins:挂载逻辑卷,绑定es的插件目录

--privileged:授予逻辑卷访问权

--network es-net :加入一个名为es-net的网络中

-p 9200:9200:端口映射配置

在浏览器中输入:http://192.168.194.131/:9200 即可看到elasticsearch的响应结果:

4.2.部署kibana

kibana可以给我们提供一个elasticsearch的可视化界面,便于我们学习。

4.2.1.部署

创建网络后,导入kibana压缩包,然后创建并启动相应容器。【和前面部署单点es一样做法】

再运行docker命令,部署kibana

docker run -d \

--name kibana \

-e ELASTICSEARCH_HOSTS=http://es:9200 \

--network=es-net \

-p 5601:5601 \

kibana:7.12.1

--network es-net :加入一个名为es-net的网络中,与elasticsearch在同一个网络中

-e ELASTICSEARCH_HOSTS=http://es:9200":设置elasticsearch的地址,因为kibana已经与elasticsearch在一个网络,因此可以用容器名直接访问elasticsearch

-p 5601:5601:端口映射配置

kibana启动一般比较慢,需要多等待一会,可以通过命令:

docker logs -f kibana

查看运行日志,当查看到下面的日志,说明成功:

此时,在浏览器输入地址访问:http://192.168.194.131:5601,即可看到结果如下图:

kibana左侧中提供了一个DevTools界面:

这个界面中可以编写DSL来操作elasticsearch。并且对DSL语句有自动补全功能。

4.3.安装IK分词器

4.3.1.在线安装ik插件(较慢)

# 进入容器内部

docker exec -it elasticsearch /bin/bash

# 在线下载并安装

./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.12.1/elasticsearch-analysis-ik-7.12.1.zip

#退出

exit

#重启容器

docker restart elasticsearch

4.3.2.离线安装ik插件(推荐)

1)查看数据卷目录

安装插件需要知道elasticsearch的plugins目录位置,而我们用了数据卷挂载,因此需要查看elasticsearch的数据卷目录,通过下面命令查看:

docker volume inspect es-plugins

显示结果:

[

{

"CreatedAt": "2022-05-06T10:06:34+08:00",

"Driver": "local",

"Labels": null,

"Mountpoint": "/var/lib/docker/volumes/es-plugins/_data",

"Name": "es-plugins",

"Options": null,

"Scope": "local"

}

]

说明plugins目录被挂载到了:/var/lib/docker/volumes/es-plugins/_data 这个目录中。

2)解压缩分词器安装包

下面我们需要把课前资料中的ik分词器解压缩,重命名为ik

3)上传到es容器的插件数据卷中

也就是/var/lib/docker/volumes/es-plugins/_data :

4)重启容器

# 4、重启容器

docker restart es

# 查看es日志

docker logs -f es

5)测试:

IK分词器包含两种模式:

ik_smart:最少切分

ik_max_word:最细切分

在kibana的Dev tools中输入以下代码:

”analyzer“ 就是选择分词器模式

GET /_analyze

{

"analyzer": "ik_max_word",

"text": "黑马程序员学习java太棒了"

}

结果:

{

"tokens" : [

{

"token" : "黑马",

"start_offset" : 0,

"end_offset" : 2,

"type" : "CN_WORD",

"position" : 0

},

{

"token" : "程序员",

"start_offset" : 2,

"end_offset" : 5,

"type" : "CN_WORD",

"position" : 1

},

{

"token" : "程序",

"start_offset" : 2,

"end_offset" : 4,

"type" : "CN_WORD",

"position" : 2

},

{

"token" : "员",

"start_offset" : 4,

"end_offset" : 5,

"type" : "CN_CHAR",

"position" : 3

},

{

"token" : "学习",

"start_offset" : 5,

"end_offset" : 7,

"type" : "CN_WORD",

"position" : 4

},

{

"token" : "java",

"start_offset" : 7,

"end_offset" : 11,

"type" : "ENGLISH",

"position" : 5

},

{

"token" : "太棒了",

"start_offset" : 11,

"end_offset" : 14,

"type" : "CN_WORD",

"position" : 6

},

{

"token" : "太棒",

"start_offset" : 11,

"end_offset" : 13,

"type" : "CN_WORD",

"position" : 7

},

{

"token" : "了",

"start_offset" : 13,

"end_offset" : 14,

"type" : "CN_CHAR",

"position" : 8

}

]

}

4.3.3 扩展词词典

随着互联网的发展,“造词运动”也越发的频繁。出现了很多新的词语,在原有的词汇列表中并不存在。比如:“奥力给”,“白嫖” 等。

所以我们的词汇也需要不断的更新,IK分词器提供了扩展词汇的功能。

1)打开IK分词器config目录:

2)在IKAnalyzer.cfg.xml配置文件内容添加:

IK Analyzer 扩展配置

ext.dic

3)新建一个 ext.dic,可以参考config目录下复制一个配置文件进行修改

白嫖

奥力给

4)重启elasticsearch

docker restart es

# 查看 日志

docker logs -f elasticsearch

日志中已经成功加载ext.dic配置文件

5)测试效果:

GET /_analyze

{

"analyzer": "ik_max_word",

"text": "传智播客Java就业超过90%,奥力给!"

}

注意当前文件的编码必须是 UTF-8 格式,严禁使用Windows记事本编辑

4.3.4 停用词词典

在互联网项目中,在网络间传输的速度很快,所以很多语言是不允许在网络上传递的,如:关于宗教、政治等敏感词语,那么我们在搜索时也应该忽略当前词汇。

IK分词器也提供了强大的停用词功能,让我们在索引时就直接忽略当前的停用词汇表中的内容。

1)IKAnalyzer.cfg.xml配置文件内容添加:

IK Analyzer 扩展配置

ext.dic

stopword.dic

3)在 stopword.dic 添加停用词

大帅逼

4)重启elasticsearch

# 重启服务

docker restart es

docker restart kibana

# 查看 日志

docker logs -f elasticsearch

日志中已经成功加载stopword.dic配置文件

5)测试效果:

GET /_analyze

{

"analyzer": "ik_max_word",

"text": "我是真的会谢Java就业率超过95%,大帅逼都点赞白嫖,奥力给!"

}

注意当前文件的编码必须是 UTF-8 格式,严禁使用Windows记事本编辑

索引库操作

索引库就类似数据库表,mapping映射就类似表的结构。

我们要向es中存储数据,必须先创建“库”和“表”。

1. Mapping映射属性

mapping是对索引库中文档的约束,常见的mapping属性包括:

type:字段数据类型,常见的简单类型有:

字符串:text(可分词的文本)、keyword(精确值,例如:品牌、国家、ip地址)

keyword类型只能整体搜索,不支持搜索部分内容

数值:long、integer、short、byte、double、float、

布尔:boolean

日期:date

对象:object

index:是否创建索引,默认为true

analyzer:使用哪种分词器

properties:该字段的子字段

例如下面的json文档:

{

    "age": 21,

    "weight": 52.1,

    "isMarried": false,

    "info": "真相只有一个!",

"email": "zy@itcast.cn",

"score": [99.1, 99.5, 98.9],

    "name": {

        "firstName": "柯",

        "lastName": "南"

    }

}

对应的每个字段映射(mapping):

age:类型为 integer;参与搜索,因此需要index为true;无需分词器

weight:类型为float;参与搜索,因此需要index为true;无需分词器

isMarried:类型为boolean;参与搜索,因此需要index为true;无需分词器

info:类型为字符串,需要分词,因此是text;参与搜索,因此需要index为true;分词器可以用ik_smart

email:类型为字符串,但是不需要分词,因此是keyword;不参与搜索,因此需要index为false;无需分词器

score:虽然是数组,但是我们只看元素的类型,类型为float;参与搜索,因此需要index为true;无需分词器

name:类型为object,需要定义多个子属性

name.firstName;类型为字符串,但是不需要分词,因此是keyword;参与搜索,因此需要index为true;无需分词器

name.lastName;类型为字符串,但是不需要分词,因此是keyword;参与搜索,因此需要index为true;无需分词器

2. 索引库的CRUD

CRUD简单描述:

创建索引库:PUT /索引库名

查询索引库:GET /索引库名

删除索引库:DELETE /索引库名

修改索引库(添加字段):PUT /索引库名/_mapping

这里统一使用Kibana编写DSL的方式来演示。

2.1 创建索引库和映射

基本语法:

请求方式:PUT

请求路径:/索引库名,可以自定义

请求参数:mapping映射

格式:

PUT /索引库名称

{

  "mappings": {

    "properties": {

      "字段名":{

        "type": "text",

        "analyzer": "ik_smart"

      },

      "字段名2":{

        "type": "keyword",

        "index": "false"

      },

      "字段名3":{

        "properties": {

          "子字段": {

            "type": "keyword"

          }

        }

      },

// ...略

    }

  }

}

示例:

PUT /conan

{

"mappings": {

"properties": {

"column1":{

"type": "text",

"analyzer": "ik_smart"

},

"column2":{

"type": "keyword",

"index": "false"

},

"column3":{

"properties": {

"子字段1": {

"type": "keyword"

},

"子字段2": {

"type": "keyword"

}

}

},

// ...略

}

}

}

2.2 查询索引库

基本语法:

请求方式:GET

请求路径:/索引库名

请求参数:无

格式:

GET /索引库名

示例:

2.3 修改索引库

这里的修改是只能增加新的字段到mapping中

倒排索引结构虽然不复杂,但是一旦数据结构改变(比如改变了分词器),就需要重新创建倒排索引,这简直是灾难。因此索引库一旦创建,无法修改mapping。

虽然无法修改mapping中已有的字段,但是却允许添加新的字段到mapping中,因为不会对倒排索引产生影响。

语法说明:

PUT /索引库名/_mapping

{

"properties": {

"新字段名":{

"type": "integer"

}

}

}

示例:

2.4 删除索引库

语法:

请求方式:DELETE

请求路径:/索引库名

请求参数:无

格式:

DELETE /索引库名

在kibana中测试:

文档操作

文档操作有哪些?

创建文档:POST /{索引库名}/_doc/文档id

查询文档:GET /{索引库名}/_doc/文档id

删除文档:DELETE /{索引库名}/_doc/文档id

修改文档:

全量修改:PUT /{索引库名}/_doc/文档id

增量修改:POST /{索引库名}/_update/文档id { "doc": {字段}}

1. 文档的CRUD

1.1 新增文档

语法:

POST /索引库名/_doc/文档id

{

    "字段1": "值1",

    "字段2": "值2",

    "字段3": {

        "子属性1": "值3",

        "子属性2": "值4"

    },

// ...

}

示例:

POST /heima/_doc/1

{

    "info": "真相只有一个!",

    "email": "zy@itcast.cn",

    "name": {

        "firstName": "柯",

        "lastName": "南"

    }

}

响应:

1.2 查询文档

根据rest风格,新增是post,查询应该是get,不过查询一般都需要条件,这里我们把文档id带上。

语法:

GET /{索引库名称}/_doc/{id}

//批量查询:查询该索引库下的全部文档

GET /{索引库名称}/_search

通过kibana查看数据:

GET /heima/_doc/1

查看结果:

1.3 删除文档

删除使用DELETE请求,同样,需要根据id进行删除:

语法:

DELETE /{索引库名}/_doc/id值

示例:

# 根据id删除数据

DELETE /heima/_doc/1

结果:

1.4 修改文档

修改有两种方式:

全量修改:直接覆盖原来的文档

增量修改:修改文档中的部分字段

1.4.1 全量修改

全量修改是覆盖原来的文档,其本质是:

根据指定的id删除文档

新增一个相同id的文档

注意:如果根据id删除时,id不存在,第二步的新增也会执行,也就从修改变成了新增操作了。

语法:

PUT /{索引库名}/_doc/文档id

{

    "字段1": "值1",

    "字段2": "值2",

// ... 略

}

示例:

PUT /heima/_doc/1

{

    "info": "黑马程序员高级Java讲师",

    "email": "zy@itcast.cn",

    "name": {

        "firstName": "云",

        "lastName": "赵"

    }

}

1.4.2 增量修改

增量修改是只修改指定id匹配的文档中的部分字段。

语法:

POST /{索引库名}/_update/文档id

{

    "doc": {

"字段名": "新的值",

}

}

示例:

POST /heima/_update/1

{

  "doc": {

    "email": "ZhaoYun@itcast.cn"

  }

}

RestAPI

ES官方提供了各种不同语言的客户端,用来操作ES。这些客户端的本质就是组装DSL语句,通过http请求发送给ES。官方文档地址:https://www.elastic.co/guide/en/elasticsearch/client/index.html

其中的Java Rest Client又包括两种:

Java Low Level Rest Client

Java High Level Rest Client

我们使用的是Java HighLevel Rest Client客户端API

API操作索引库

JavaRestClient操作elasticsearch的流程基本类似。核心是client.indices()方法来获取索引库的操作对象。

索引库操作的基本步骤:【可以根据发送请求那步的第一个参数,发过来判断需要创建什么XXXXRequest】

初始化RestHighLevelClient

创建XxxIndexRequest。XXX是Create、Get、Delete

准备DSL( Create时需要,其它是无参)

发送请求。调用RestHighLevelClient#indices().xxx()方法,xxx是create、exists、delete

1. mapping映射分析

根据MySQL数据库表结构(建表语句),去写索引库结构JSON。表和索引库一一对应

注意:地理坐标、组合字段。索引库里的地理坐标是一个字段:坐标:维度,精度 。copy_to组合字段作用是供用户查询(输入关键字可以查询多个字段)

创建索引库,最关键的是mapping映射,而mapping映射要考虑的信息包括:

字段名

字段数据类型

是否参与搜索

是否需要分词

如果分词,分词器是什么?

其中:

字段名、字段数据类型,可以参考数据表结构的名称和类型

是否参与搜索要分析业务来判断,例如图片地址,就无需参与搜索

是否分词呢要看内容,内容如果是一个整体就无需分词,反之则要分词

分词器,我们可以统一使用ik_max_word

来看下酒店数据的索引库结构:

PUT /hotel

{

"mappings": {

"properties": {

"id": {

"type": "keyword"

},

"name":{

"type": "text",

"analyzer": "ik_max_word",

"copy_to": "all"

},

"address":{

"type": "keyword",

"index": false

},

"price":{

"type": "integer"

},

"score":{

"type": "integer"

},

"brand":{

"type": "keyword",

"copy_to": "all"

},

"city":{

"type": "keyword",

"copy_to": "all"

},

"starName":{

"type": "keyword"

},

"business":{

"type": "keyword"

},

"location":{

"type": "geo_point"

},

"pic":{

"type": "keyword",

"index": false

},

"all":{

"type": "text",

"analyzer": "ik_max_word"

}

}

}

}

几个特殊字段说明:

location:地理坐标,里面包含精度、纬度

all:一个组合字段,其目的是将多字段的值 利用copy_to合并,提供给用户搜索

地理坐标说明:

copy_to说明:

2.初始化RestClient

在elasticsearch提供的API中,与elasticsearch一切交互都封装在一个名为RestHighLevelClient的类中,必须先完成这个对象的初始化,建立与elasticsearch的连接。

分为三步:

1)引入es的RestHighLevelClient依赖:

org.elasticsearch.client

elasticsearch-rest-high-level-client

2)因为SpringBoot默认的ES版本是7.6.2,所以我们需要覆盖默认的ES版本:

1.8

7.12.1

3)初始化RestHighLevelClient:这里一般在启动类或者配置类里注入该Bean,用于告诉Java 访问ES的ip地址

初始化的代码如下:

@Bean

public RestHighLevelClient client(){

return new RestHighLevelClient(RestClient.builder(

HttpHost.create("http://192.168.150.101:9200")

));

}

这里为了单元测试方便,我们创建一个测试类HotelIndexTest,然后将初始化的代码编写在@BeforeEach方法中:

package cn.itcast.hotel;

import org.apache.http.HttpHost;

import org.elasticsearch.client.RestHighLevelClient;

import org.junit.jupiter.api.AfterEach;

import org.junit.jupiter.api.BeforeEach;

import org.junit.jupiter.api.Test;

import java.io.IOException;

public class HotelIndexTest {

private RestHighLevelClient client;

@BeforeEach

void setUp() {

this.client = new RestHighLevelClient(RestClient.builder(

HttpHost.create("http://192.168.150.101:9200")

));

}

@AfterEach

void tearDown() throws IOException {

this.client.close();

}

}

3. 索引库CRUD

3.1 创建索引库

代码分为三步:

1)创建Request对象。因为是创建索引库的操作,因此Request是CreateIndexRequest。

2)添加请求参数,其实就是DSL的JSON参数部分。因为json字符串很长,这里是定义了静态字符串常量MAPPING_TEMPLATE,让代码看起来更加优雅。

3)发送请求,client.indices()方法的返回值是IndicesClient类型,封装了所有与索引库操作有关的方法。

创建索引库的API如下:

代码:

在hotel-demo的cn.itcast.hotel.constants包下,创建一个类,定义mapping映射的JSON字符串常量:

package cn.itcast.hotel.constants;

public class HotelConstants {

public static final String MAPPING_TEMPLATE = "{\n" +

" \"mappings\": {\n" +

" \"properties\": {\n" +

" \"id\": {\n" +

" \"type\": \"keyword\"\n" +

" },\n" +

" \"name\":{\n" +

" \"type\": \"text\",\n" +

" \"analyzer\": \"ik_max_word\",\n" +

" \"copy_to\": \"all\"\n" +

" },\n" +

" \"address\":{\n" +

" \"type\": \"keyword\",\n" +

" \"index\": false\n" +

" },\n" +

" \"price\":{\n" +

" \"type\": \"integer\"\n" +

" },\n" +

" \"score\":{\n" +

" \"type\": \"integer\"\n" +

" },\n" +

" \"brand\":{\n" +

" \"type\": \"keyword\",\n" +

" \"copy_to\": \"all\"\n" +

" },\n" +

" \"city\":{\n" +

" \"type\": \"keyword\",\n" +

" \"copy_to\": \"all\"\n" +

" },\n" +

" \"starName\":{\n" +

" \"type\": \"keyword\"\n" +

" },\n" +

" \"business\":{\n" +

" \"type\": \"keyword\"\n" +

" },\n" +

" \"location\":{\n" +

" \"type\": \"geo_point\"\n" +

" },\n" +

" \"pic\":{\n" +

" \"type\": \"keyword\",\n" +

" \"index\": false\n" +

" },\n" +

" \"all\":{\n" +

" \"type\": \"text\",\n" +

" \"analyzer\": \"ik_max_word\"\n" +

" }\n" +

" }\n" +

" }\n" +

"}";

}

在hotel-demo中的HotelIndexTest测试类中,编写单元测试,实现创建索引:

@Test

void createHotelIndex() throws IOException {

// 1.创建Request对象

CreateIndexRequest request = new CreateIndexRequest("hotel");

// 2.准备请求的参数:DSL语句

request.source(MAPPING_TEMPLATE, XContentType.JSON);

// 3.发送请求

client.indices().create(request, RequestOptions.DEFAULT);

}

3.2 删除索引库

三步走:

1)创建Request对象。这次是DeleteIndexRequest对象

2)准备参数。这里是无参

3)发送请求。改用delete方法

删除索引库的DSL语句非常简单:

DELETE /hotel

在hotel-demo中的HotelIndexTest测试类中,编写单元测试,实现删除索引:

@Test

void testDeleteHotelIndex() throws IOException {

// 1.创建Request对象

DeleteIndexRequest request = new DeleteIndexRequest("hotel");

// 2.发送请求

client.indices().delete(request, RequestOptions.DEFAULT);

}

3.3 查询索引库

三步走:

1)创建Request对象。这次是GetIndexRequest对象

2)准备参数。这里是无参

3)发送请求。改用exists方法

判断索引库是否存在,本质就是查询,对应的DSL是:

GET /hotel

@Test

void testExistsHotelIndex() throws IOException {

// 1.创建Request对象

GetIndexRequest request = new GetIndexRequest("hotel");

// 2.发送请求

boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);

// 3.输出

System.err.println(exists ? "索引库已经存在!" : "索引库不存在!");

}

API操作文档

这里更多的是先读取Mysql中的数据,然后再存进ES中。

文档操作的基本步骤:【可以根据发送请求那步的第一个参数,发过来判断需要创建什么XXXXRequest】

初始化RestHighLevelClient

创建XxxRequest。XXX是Index、Get、Update、Delete、Bulk

准备参数(Index、Update、Bulk时需要)

发送请求。调用RestHighLevelClient#.xxx()方法,xxx是index、get、update、delete、bulk

解析结果(Get时需要)

1. 初始化RestClient

在elasticsearch提供的API中,与elasticsearch一切交互都封装在一个名为RestHighLevelClient的类中,必须先完成这个对象的初始化,建立与elasticsearch的连接。

分为三步:

1)引入es的RestHighLevelClient依赖:

org.elasticsearch.client

elasticsearch-rest-high-level-client

2)因为SpringBoot默认的ES版本是7.6.2,所以我们需要覆盖默认的ES版本:

1.8

7.12.1

3)初始化RestHighLevelClient:这里一般写在最前面,用于告诉Java 访问ES的ip地址

初始化的代码如下:

RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(

HttpHost.create("http://192.168.150.101:9200")

));

这里为了单元测试方便,我们创建一个测试类HotelIndexTest,然后将初始化的代码编写在@BeforeEach方法中:

package cn.itcast.hotel;

import org.apache.http.HttpHost;

import org.elasticsearch.client.RestHighLevelClient;

import org.junit.jupiter.api.AfterEach;

import org.junit.jupiter.api.BeforeEach;

import org.junit.jupiter.api.Test;

import java.io.IOException;

public class HotelIndexTest {

private RestHighLevelClient client;

@BeforeEach

void setUp() {

this.client = new RestHighLevelClient(RestClient.builder(

HttpHost.create("http://192.168.150.101:9200")

));

}

@AfterEach

void tearDown() throws IOException {

this.client.close();

}

}

2. 文档CRUD

2.0 批量导入文档

三步走:

1)创建Request对象。这里是BulkRequest

2)准备参数。批处理的参数,就是其它Request对象,这里就是多个IndexRequest

3)发起请求。这里是批处理,调用的方法为client.bulk()方法

案例需求:利用BulkRequest批量将数据库数据导入到索引库中。

步骤如下:

利用mybatis-plus查询酒店数据

将查询到的酒店数据(Hotel)转换为文档类型数据(HotelDoc)

利用JavaRestClient中的BulkRequest批处理,实现批量新增文档

语法说明:

批量处理BulkRequest,其本质就是将多个普通的CRUD请求组合在一起发送。

其中提供了一个add方法,用来添加其他请求:

可以看到,能添加的请求包括:

IndexRequest,也就是新增

UpdateRequest,也就是修改

DeleteRequest,也就是删除

因此Bulk中添加了多个IndexRequest,就是批量新增功能了。示例:

我们在导入酒店数据时,将上述代码改造成for循环处理即可。

在hotel-demo的HotelDocumentTest测试类中,编写单元测试:

@Test

void testBulkRequest() throws IOException {

// 批量查询酒店数据

List hotels = hotelService.list();

// 1.创建Request

BulkRequest request = new BulkRequest();

// 2.准备参数,添加多个新增的Request

for (Hotel hotel : hotels) {

// 2.1.转换为文档类型HotelDoc

HotelDoc hotelDoc = new HotelDoc(hotel);

// 2.2.创建新增文档的Request对象

request.add(new IndexRequest("hotel")

.id(hotelDoc.getId().toString())

.source(JSON.toJSONString(hotelDoc), XContentType.JSON));

}

// 3.发送请求

client.bulk(request, RequestOptions.DEFAULT);

}

2.1 批量新增文档

四步走:

0)创建索引库实体类

1)创建Request对象

2)准备请求参数,也就是DSL中的JSON文档

3)发送请求 (注意:这里直接使用client.xxx()的API,不再需要client.indices()了)

我们要将数据库的酒店数据查询出来,写入elasticsearch中。

1)创建索引库实体类

一般实体类里包含经纬度都需要创建一个新的实体类,将经纬度拼成一个字段

数据库查询后的结果是一个Hotel类型的对象。结构如下:

@Data

@TableName("tb_hotel")

public class Hotel {

@TableId(type = IdType.INPUT)

private Long id;

private String name;

private String address;

private Integer price;

private Integer score;

private String brand;

private String city;

private String starName;

private String business;

private String longitude;

private String latitude;

private String pic;

}

与我们的索引库结构存在差异:

longitude和latitude需要合并为location

因此,我们需要定义一个新的类型,与索引库结构吻合:

package cn.itcast.hotel.pojo;

import lombok.Data;

import lombok.NoArgsConstructor;

@Data

@NoArgsConstructor

public class HotelDoc {

private Long id;

private String name;

private String address;

private Integer price;

private Integer score;

private String brand;

private String city;

private String starName;

private String business;

private String location;

private String pic;

public HotelDoc(Hotel hotel) {

this.id = hotel.getId();

this.name = hotel.getName();

this.address = hotel.getAddress();

this.price = hotel.getPrice();

this.score = hotel.getScore();

this.brand = hotel.getBrand();

this.city = hotel.getCity();

this.starName = hotel.getStarName();

this.business = hotel.getBusiness();

this.location = hotel.getLatitude() + ", " + hotel.getLongitude();

this.pic = hotel.getPic();

}

}

2)新增代码

新增文档的DSL语句如下:

POST /{索引库名}/_doc/1

{

"name": "Jack",

"age": 21

}

对应的java代码如图:

我们导入酒店数据,基本流程一致,但是需要考虑几点变化:

酒店数据来自于数据库,我们需要先查询出来,得到hotel对象

hotel对象需要转为HotelDoc对象

HotelDoc需要序列化为json格式

在hotel-demo的HotelDocumentTest测试类中,编写单元测试:

@Test

void testAddDocument() throws IOException {

// 批量查询酒店数据

List hotels = hotelService.list();

// 1.创建Request

BulkRequest request = new BulkRequest();

// 2.准备参数,添加多个新增的Request

for (Hotel hotel : hotels) {

// 2.1.转换为文档类型HotelDoc

HotelDoc hotelDoc = new HotelDoc(hotel);

// 2.2.创建新增文档的Request对象

request.add(new IndexRequest("hotel")

.id(hotelDoc.getId().toString())

.source(JSON.toJSONString(hotelDoc), XContentType.JSON));//实体类转JSON,指定JSON格式

request.add(new IndexRequest("xxx")...)

}

// 3.发送请求

client.bulk(request, RequestOptions.DEFAULT);

}

2.2 查询文档

查询文档是根据id查询的,所以没有批量查询

三步走:

1)准备Request对象。这次是查询,所以是GetRequest

2)发送请求,得到结果。因为是查询,这里调用client.get()方法

3)解析结果,就是对JSON做反序列化

查询的DSL语句如下:

GET /hotel/_doc/{id}

非常简单,因此代码大概分两步:

准备Request对象

发送请求

不过查询的目的是得到结果,解析为HotelDoc,因此难点是结果的解析。完整代码如下:

可以看到,结果是一个JSON,其中文档放在一个_source属性中,因此解析就是拿到_source,使用工具反序列化为Java对象即可。

在hotel-demo的HotelDocumentTest测试类中,编写单元测试:

@Test

void testGetDocumentById() throws IOException {

// 1.准备Request

GetRequest request = new GetRequest("hotel", "61082");

// 2.发送请求,得到响应

GetResponse response = client.get(request, RequestOptions.DEFAULT);

// 3.解析响应结果

String json = response.getSourceAsString();

HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);

System.out.println(hotelDoc);

}

2.3 批量删除文档

三步走:

1)准备Request对象,因为是删除,这次是DeleteRequest对象。要指定索引库名和id

2)准备参数,无参

3)发送请求。因为是删除,所以是client.delete()方法

删除的DSL为是这样的:

DELETE /hotel/_doc/{id}

在hotel-demo的HotelDocumentTest测试类中,编写单元测试:

@Test

void testDeleteDocument() throws IOException {

//0.查询数据库中的数据

List list = hotelService.list();

// 1.创建Request

BulkRequest request = new BulkRequest();

//2.批量转换实体类,顺便写入到ES中

for (Hotel hotel : list) {

//2.1转换实体类

HotelDoc hotelDoc =new HotelDoc(hotel);

//2.2写入ES

request.add(new DeleteRequest("hotel")

.id(hotel.getId().toString()));

}

//3.发送请求

client.bulk(request,RequestOptions.DEFAULT);

}

2.4 批量修改文档

三步走:

1)准备Request对象。这次是修改,所以是UpdateRequest

2)准备参数。也就是JSON文档,里面包含要修改的字段

3)更新文档。这里调用client.update()方法

修改有两种方式:

全量修改:本质是先根据id删除,再新增

增量修改:修改文档中的指定字段值

在RestClient的API中,全量修改与新增的API完全一致,判断依据是ID:

如果新增时,ID已经存在,则修改

如果新增时,ID不存在,则新增

只演示增量修改:

代码示例如图:

在hotel-demo的HotelDocumentTest测试类中,编写单元测试:

@Test

void testUpdateDocument() throws IOException {

//0.查询数据库中的数据

List list = hotelService.list();

// 1.创建Request

BulkRequest request = new BulkRequest();

//2.批量转换实体类,顺便写入到ES中

for (Hotel hotel : list) {

//2.1转换实体类

HotelDoc hotelDoc =new HotelDoc(hotel);

//2.2写入ES

request.add(new UpdateRequest("hotel",hotel.getId().toString())

.doc(

"price", "952",

"starName", "四钻"

));

}

//3.发送请求

client.bulk(request,RequestOptions.DEFAULT);

}

ES搜索引擎

elasticsearch的查询依然是基于JSON风格的DSL来实现的。

1. DSL设置查询条件

1.1 DSL查询分类

Elasticsearch提供了基于JSON的DSL(Domain Specific Language)来定义查询。常见的查询类型包括:

查询所有:查询出所有数据,一般测试用。例如:match_all

全文检索(full text)查询:利用分词器对用户输入内容分词,然后去倒排索引库中匹配。例如:

match_query

multi_match_query

精确查询:根据精确词条值查找数据,一般是查找keyword、数值、日期、boolean等类型字段。例如:

ids

range

term

地理(geo)查询:根据经纬度查询。例如:

geo_distance

geo_bounding_box

复合(compound)查询:复合查询可以将上述各种查询条件组合起来,合并查询条件。例如:

bool

function_score

查询的语法基本一致:

GET /indexName/_search

{

  "query": {

    "查询类型": {

      "查询条件": "条件值"

    }

  }

}

我们以查询所有为例,其中:

查询类型为match_all

没有查询条件

// 查询所有

GET /indexName/_search

{

  "query": {

    "match_all": {

}

  }

}

其它查询无非就是查询类型、查询条件的变化。

1.2 全文检索查询

match和multi_match的区别是什么?

match:根据一个字段查询【推荐:使用copy_to构造all字段】

multi_match:根据多个字段查询,参与查询字段越多,查询性能越差

注:搜索字段越多,对查询性能影响越大,因此建议采用copy_to,然后单字段查询的方式。

1.2.1 使用场景

全文检索查询的基本流程如下:

对用户搜索的内容做分词,得到词条

根据词条去倒排索引库中匹配,得到文档id

根据文档id找到文档,返回给用户

比较常用的场景包括:

商城的输入框搜索

百度输入框搜索

例如京东:

因为是拿着词条去匹配,因此参与搜索的字段也必须是可分词的text类型的字段。

常见的全文检索查询包括:

match查询:单字段查询

multi_match查询:多字段查询,任意一个字段符合条件就算符合查询条件

1.2.2 match查询

match查询语法如下:

GET /indexName/_search

{

  "query": {

    "match": {

      "FIELD": "TEXT"

    }

  }

}

match查询示例:

1.2.3 mulit_match查询

mulit_match语法如下:

GET /indexName/_search

{

  "query": {

    "multi_match": {

      "query": "TEXT",

      "fields": ["FIELD1", " FIELD12"]

    }

  }

}

multi_match查询示例:

1.3 精准查询

精准查询类型:

term查询:根据词条精确匹配,一般搜索keyword类型、数值类型、布尔类型、日期类型字段

range查询:根据数值范围查询,可以是数值、日期的范围

精确查询一般是查找keyword、数值、日期、boolean等类型字段。所以不会对搜索条件分词。常见的有:

term:根据词条精确值查询

range:根据值的范围查询

1.3.1 term查询

因为精确查询的字段搜时不分词的字段,因此查询的条件也必须是不分词的词条。查询时,用户输入的内容跟自动值完全匹配时才认为符合条件。如果用户输入的内容过多,反而搜索不到数据。

语法说明:

// term查询

GET /indexName/_search

{

  "query": {

    "term": {

      "FIELD": {

        "value": "VALUE"

      }

    }

  }

}

示例:

当我搜索的是精确词条时,能正确查询出结果:

但是,当我搜索的内容不是词条,而是多个词语形成的短语时,反而搜索不到:

1.3.2 range查询

范围查询,一般应用在对数值类型做范围过滤的时候。比如做价格范围过滤。

基本语法:

// range查询

GET /indexName/_search

{

  "query": {

    "range": {

      "FIELD": {

        "gte": 10, // 这里的gte代表大于等于,gt则代表大于

        "lte": 20 // lte代表小于等于,lt则代表小于

      }

    }

  }

}

示例:

1.4 地理坐标查询

所谓的地理坐标查询,其实就是根据经纬度查询,官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/geo-queries.html

常见的使用场景包括:

携程:搜索我附近的酒店

滴滴:搜索我附近的出租车

微信:搜索我附近的人

附近的酒店:

附近的车:

1.4.1 矩形范围查询

很少有业务有这种需求

矩形范围查询,也就是geo_bounding_box查询,查询坐标落在某个矩形范围的所有文档:

查询时,需要指定矩形的左上、右下两个点的坐标,然后画出一个矩形,落在该矩形内的都是符合条件的点。

语法如下:

// geo_bounding_box查询

GET /indexName/_search

{

  "query": {

    "geo_bounding_box": {

      "FIELD": {

        "top_left": { // 左上点

          "lat": 31.1,

          "lon": 121.5

        },

        "bottom_right": { // 右下点

          "lat": 30.9,

          "lon": 121.7

        }

      }

    }

  }

}

1.4.2 附近(圆形)查询

附近查询,也叫做距离查询(geo_distance):查询到指定中心点小于某个距离值的所有文档。

换句话来说,在地图上找一个点作为圆心,以指定距离为半径,画一个圆,落在圆内的坐标都算符合条件:

语法说明:

// geo_distance 查询

GET /indexName/_search

{

  "query": {

    "geo_distance": {

      "distance": "15km", // 半径

      "FIELD": "31.21,121.5" // 圆心

    }

  }

}

示例:

我们先搜索陆家嘴附近15km的酒店:

发现共有47家酒店。

1.5 复合查询

复合(compound)查询:复合查询可以将其它简单查询组合起来,实现更复杂的搜索逻辑。常见的有两种:

fuction score:算分函数查询,可以控制文档相关性算分,控制文档排名

bool query:布尔查询,利用逻辑关系组合多个其它的查询,实现复杂搜索

1.5.0 复合查询归纳

GET /hotel/_search

{

"query": {

    "function_score": {

"query": { // 原始查询,可以是任意条件

"bool": {

"must": [

{"term": {"city": "上海" }}

],

"should": [

{"term": {"brand": "皇冠假日" }},

{"term": {"brand": "华美达" }}

],

"must_not": [

{ "range": { "price": { "lte": 500 } }}

],

"filter": [

{ "range": {"score": { "gte": 45 } }}

]

}

},

      "functions": [ // 算分函数

        {

          "filter": { // 满足的条件,品牌必须是如家【品牌是如家的才加分,这里是加分条件】

            "term": {

              "brand": "如家"

            }

          },

          "weight": 2 // 算分权重为2

        }

      ],

"boost_mode": "sum" // 加权模式,求和

    }

  }

}

1.5.1 相关性算分

elasticsearch会根据词条和文档的相关度做打分,算法由两种:

TF-IDF算法

BM25算法,elasticsearch5.1版本后采用的算法

当我们利用match查询时,文档结果会根据与搜索词条的关联度打分(_score),返回结果时按照分值降序排列。

例如,我们搜索 "虹桥如家",结果如下:

[

  {

    "_score" : 17.850193,

    "_source" : {

      "name" : "虹桥如家酒店真不错",

    }

  },

  {

    "_score" : 12.259849,

    "_source" : {

      "name" : "外滩如家酒店真不错",

    }

  },

  {

    "_score" : 11.91091,

    "_source" : {

      "name" : "迪士尼如家酒店真不错",

    }

  }

]

在elasticsearch中,早期使用的打分算法是TF-IDF算法,公式如下:

在后来的5.1版本升级中,elasticsearch将算法改进为BM25算法,公式如下:

TF-IDF算法有一各缺陷,就是词条频率越高,文档得分也会越高,单个词条对文档影响较大。而BM25则会让单个词条的算分有一个上限,曲线更加平滑:

1.5.2 算分函数查询

在搜索出来的结果的分数基础上,再手动与指定的数字进行一定运算来改变算分,从而改变结果的排序。

function score query定义的三要素是什么?

过滤条件:哪些文档要加分

算分函数:如何计算function score

加权方式:function score 与 query score如何运算

根据相关度打分是比较合理的需求,但合理的不一定是产品经理需要的。

以百度为例,你搜索的结果中,并不是相关度越高排名越靠前,而是谁掏的钱多排名就越靠前。如图:

要想认为控制相关性算分,就需要利用elasticsearch中的function score 查询了。

function score 查询

1)语法说明

function score 查询中包含四部分内容:

原始查询条件:query部分,基于这个条件搜索文档,并且基于BM25算法给文档打分,原始算分(query score)

过滤条件:filter部分,符合该条件的文档才会重新算分

算分函数:符合filter条件的文档要根据这个函数做运算,得到的函数算分(function score),有四种函数

weight:函数结果是常量

field_value_factor:以文档中的某个字段值作为函数结果

random_score:以随机数作为函数结果

script_score:自定义算分函数算法

运算模式:算分函数的结果、原始查询的相关性算分,两者之间的运算方式,包括:

multiply:相乘

replace:用function score替换query score

其它,例如:sum、avg、max、min

function score的运行流程如下:

1)根据原始条件查询搜索文档,并且计算相关性算分,称为原始算分(query score)

2)根据过滤条件,过滤文档

3)符合过滤条件的文档,基于算分函数运算,得到函数算分(function score)

4)将原始算分(query score)和函数算分(function score)基于运算模式做运算,得到最终结果,作为相关性算分。

2)举例

需求:给“如家”这个品牌的酒店排名靠前一些

翻译一下这个需求,转换为之前说的四个要点:

原始条件:不确定,可以任意变化

过滤条件:brand = "如家"

算分函数:可以简单粗暴,直接给固定的算分结果,weight

运算模式:比如求和

因此最终的DSL语句如下:

GET /hotel/_search

{

  "query": {

    "function_score": {

      "query": { .... }, // 原始查询,可以是任意条件

      "functions": [ // 算分函数

        {

          "filter": { // 满足的条件,品牌必须是如家【品牌是如家的才加分,这里是加分条件】

            "term": {

              "brand": "如家"

            }

          },

          "weight": 2 // 算分权重为2

        }

      ],

"boost_mode": "sum" // 加权模式,求和

    }

  }

}

测试,在未添加算分函数时,如家得分如下:

添加了算分函数后,如家得分就提升了:

1.5.3 布尔查询

布尔查询是一个或多个查询子句的组合,每一个子句就是一个子查询。子查询的组合方式有:

must:必须匹配每个子查询,类似“与”

should:选择性匹配子查询,类似“或”

must_not:必须不匹配,不参与算分,类似“非”

filter:必须匹配,不参与算分

注意:尽量在筛选的时候多使用不参与算分的must_not和filter,以保证性能良好

比如在搜索酒店时,除了关键字搜索外,我们还可能根据品牌、价格、城市等字段做过滤:

每一个不同的字段,其查询的条件、方式都不一样,必须是多个不同的查询,而要组合这些查询,就必须用bool查询了。

需要注意的是,搜索时,参与打分的字段越多,查询的性能也越差。因此这种多条件查询时,建议这样做:

搜索框的关键字搜索,是全文检索查询,使用must查询,参与算分

其它过滤条件,采用filter查询。不参与算分

bool查询

1)语法

GET /hotel/_search

{

  "query": {

    "bool": {

      "must": [

        {"term": {"city": "上海" }}

      ],

      "should": [

        {"term": {"brand": "皇冠假日" }},

{"term": {"brand": "华美达" }}

      ],

      "must_not": [

        { "range": { "price": { "lte": 500 } }}

      ],

      "filter": [

        { "range": {"score": { "gte": 45 } }}

      ]

    }

  }

}

2)示例

需求:搜索名字包含“如家”,价格不高于400,在坐标31.21,121.5周围10km范围内的酒店。

分析:

名称搜索,属于全文检索查询,应该参与算分。放到must中

价格不高于400,用range查询,属于过滤条件,不参与算分。放到must_not中

周围10km范围内,用geo_distance查询,属于过滤条件,不参与算分。放到filter中

2. 设置搜索结果

搜索的结果可以按照用户指定的方式去处理或展示。

2.0 搜索结果种类

查询的DSL是一个大的JSON对象,包含下列属性:

query:查询条件

from和size:分页条件

sort:排序条件

highlight:高亮条件

aggs:定义聚合

示例:

2.1 排序

在使用排序后就不会进行算分了,根据排序设置的规则排列

普通字段是根据字典序排序

地理坐标是根据举例远近排序

2.1.1普通字段排序

keyword、数值、日期类型排序的排序语法基本一致。

语法:

排序条件是一个数组,也就是可以写多个排序条件。按照声明的顺序,当第一个条件相等时,再按照第二个条件排序,以此类推

(可以参考下面的图片案例)

GET /indexName/_search

{

  "query": {

    "match_all": {}

  },

  "sort": [

    {

      "FIELD": "desc"  // 排序字段、排序方式ASC、DESC

    }

  ]

}

示例:

需求描述:酒店数据按照用户评价(score)降序排序,评价相同的按照价格(price)升序排序

2.1.2 地理坐标排序

地理坐标排序略有不同。

语法说明:

GET /indexName/_search

{

  "query": {

    "match_all": {}

  },

  "sort": [

    {

      "_geo_distance" : {

          "FIELD" : "纬度,经度", // 文档中geo_point类型的字段名、目标坐标点

          "order" : "asc", // 排序方式

          "unit" : "km" // 排序的距离单位

      }

    }

  ]

}

这个查询的含义是:

指定一个坐标,作为目标点

计算每一个文档中,指定字段(必须是geo_point类型)的坐标 到目标点的距离是多少

根据距离排序

示例:

需求描述:实现对酒店数据按照到你的位置坐标的距离升序排序

提示:获取你的位置的经纬度的方式:https://lbs.amap.com/demo/jsapi-v2/example/map/click-to-get-lnglat/

假设我的位置是:31.034661,121.612282,寻找我周围距离最近的酒店。

2.2 分页

elasticsearch会禁止from+ size 超过10000的请求

elasticsearch 默认情况下只返回top10的数据。而如果要查询更多数据就需要修改分页参数了。elasticsearch中通过修改from、size参数来控制要返回的分页结果:

from:从第几个文档开始

size:总共查询几个文档

类似于mysql中的limit ?, ?

2.2.1 基本分页

分页的基本语法如下:

GET /hotel/_search

{

  "query": {

    "match_all": {}

  },

  "from": 0, // 分页开始的位置,默认为0

  "size": 10, // 期望获取的文档总数

  "sort": [

    {"price": "asc"}

  ]

}

2.2.2 深度分页

原理:elasticsearch内部分页时,必须先查询 0~1000条,然后截取其中的990 ~ 1000的这10条

现在,我要查询990~1000的数据,查询逻辑要这么写:

GET /hotel/_search

{

  "query": {

    "match_all": {}

  },

  "from": 990, // 分页开始的位置,默认为0

  "size": 10, // 期望获取的文档总数

  "sort": [

    {"price": "asc"}

  ]

}

这里是查询990开始的数据,也就是 第990~第1000条 数据。

集群情况的深度分页

针对深度分页,ES提供了两种解决方案,官方文档:

search after:分页时需要排序,原理是从上一次的排序值开始,查询下一页数据。【官方推荐】

scroll:原理将排序后的文档id形成快照,保存在内存。

不过,elasticsearch内部分页时,必须先查询 0~1000条,然后截取其中的990 ~ 1000的这10条:

查询TOP1000,如果es是单点模式,这并无太大影响。

但是elasticsearch将来一定是集群,例如我集群有5个节点,我要查询TOP1000的数据,并不是每个节点查询200条就可以了。

因为节点A的TOP200,在另一个节点可能排到10000名以外了。

因此要想获取整个集群的TOP1000,必须先查询出每个节点的TOP1000,汇总结果后,重新排名,重新截取TOP1000。

那如果我要查询9900~10000的数据呢?是不是要先查询TOP10000呢?那每个节点都要查询10000条?汇总到内存中?

当查询分页深度较大时,汇总数据过多,对内存和CPU会产生非常大的压力,因此elasticsearch会禁止from+ size 超过10000的请求。

2.3 高亮

注意:

高亮是对关键字高亮,因此搜索条件必须带有关键字,而不能是范围这样的查询。

默认情况下,高亮的字段,必须与搜索指定的字段一致,否则无法高亮

如果要对非搜索字段高亮,则需要添加一个属性:required_field_match=false

使用场景:在百度等搜索后,会对结果中出现搜索字段的部分进行高亮处理。

高亮原理

高亮显示的实现分为两步:

1)给文档中的所有关键字都添加一个标签,例如标签

2)页面给标签编写CSS样式

实现高亮

1)语法

GET /hotel/_search

{

  "query": {

    "match": {

      "FIELD": "TEXT" // 查询条件,高亮一定要使用全文检索查询

    }

  },

  "highlight": {

    "fields": { // 指定要高亮的字段

      "FIELD": { //【要和上面的查询字段FIELD一致】

        "pre_tags": "",  // 用来标记高亮字段的前置标签

        "post_tags": "" // 用来标记高亮字段的后置标签

      }

    }

  }

}

2)示例:组合字段all的案例

2.4 数据聚合

类似于mysql中的【度量(Metric)聚合】聚合语句实现AVG,MAX,MIN;以及【桶(Bucket)聚合】GroupBy实现分组

聚合(aggregations)可以让我们极其方便的实现对数据的统计、分析、运算。例如:

什么品牌的手机最受欢迎?

这些手机的平均价格、最高价格、最低价格?

这些手机每月的销售情况如何?

实现这些统计功能的比数据库的sql要方便的多,而且查询速度非常快,可以实现近实时搜索效果。

aggs代表聚合,与query同级,此时query的作用是?

限定聚合的的文档范围

聚合必须的三要素:

聚合名称

聚合类型

聚合字段

聚合可配置属性有:

size:指定聚合结果数量

order:指定聚合结果排序方式

field:指定聚合字段

2.4.1 聚合种类

注意:参加聚合的字段必须是keyword、日期、数值、布尔类型

聚合常见的有三类:

桶(Bucket)聚合:用来对文档做分组

TermAggregation:按照文档字段值分组,例如按照品牌值分组、按照国家分组

Date Histogram:按照日期阶梯分组,例如一周为一组,或者一月为一组

度量(Metric)聚合:用以计算一些值,比如:最大值、最小值、平均值等

Avg:求平均值

Max:求最大值

Min:求最小值

Stats:同时求max、min、avg、sum等

管道(pipeline)聚合:其它聚合的结果为基础做聚合

如:用桶聚合实现种类排序,然后使用度量聚合实现各个桶的最大值、最小值、平均值等

2.4.2 桶(Bucket)聚合

以统计酒店品牌种类,并对其进行数据分组

GET /hotel/_search

{

"query": { //限定要聚合的文档范围,只要添加query条件【一般在没搜索关键字时不写query】

    "range": {

      "price": {

        "lte": 200 // 只对200元以下的文档聚合

      }

    }

  }, 

  "size": 0,  // 设置size为0,结果中不包含查询结果文档,只包含聚合结果

  "aggs": { // 定义聚合

    "brandAgg": { //给聚合起个名字

      "terms": { // 聚合的类型,按照品牌值聚合,所以选择term

        "field": "brand", // 参与聚合的字段

"order": {

          "doc_count": "asc" // 对聚合结果按照doc_count升序排列

        },

        "size": 20 // 希望获取的聚合结果数量【设置多少就最多只显示多少】

      }

    }

  }

}

2.4.3 度量(Metric) and 管道(pipeline)聚合

度量聚合很少单独使用,一般是和桶聚合一并结合使用

我们对酒店按照品牌分组,形成了一个个桶。现在我们需要对桶内的酒店做运算,获取每个品牌的用户评分的min、max、avg等值。

这就要用到Metric聚合了,例如stat聚合:就可以获取min、max、avg等结果。

语法如下:

这次的score_stats聚合是在brandAgg的聚合内部嵌套的子聚合。因为我们需要在每个桶分别计算。

GET /hotel/_search

{

  "size": 0, 

  "aggs": {

    "brandAgg": { 

      "terms": { 

        "field": "brand", 

"order": {

          "scoreAgg.avg": "desc" // 对聚合结果按照指定字段降序排列

        },

        "size": 20

      },

      "aggs": { // 是brands聚合的子聚合,也就是分组后对每组分别计算

        "score_stats": { // 聚合名称

          "stats": { // 聚合类型,这里stats可以计算min、max、avg等

            "field": "score" // 聚合字段,这里是score

          }

        }

      }

    }

  }

}

另外,我们还可以给聚合结果做个排序,例如按照每个桶的酒店平均分做排序:

3. RestClient查询文档

文档的查询同样适用昨天学习的 RestHighLevelClient对象,基本步骤包括:

1)准备Request对象

2)准备请求参数

3)发起请求

4)解析响应

3.1 快速入门

查询的基本步骤是:

创建SearchRequest对象

准备Request.source(),也就是DSL。

① QueryBuilders来构建查询条件

② 传入Request.source() 的 query() 方法

发送请求,得到结果

解析结果(参考JSON结果,从外到内,逐层解析)

3.1.1 发送查询请求

代码解读:

第一步,创建SearchRequest对象,指定索引库名

第二步,利用request.source()构建DSL,DSL中可以包含查询、分页、排序、高亮等

query():代表查询条件,利用QueryBuilders.matchAllQuery()构建一个match_all查询的DSL

第三步,利用client.search()发送请求,得到响应

这里关键的API有两个,一个是request.source(),其中包含了查询、排序、分页、高亮等所有功能:

另一个是QueryBuilders,其中包含match、term、function_score、bool等各种查询:

3.1.2 解析响应结果

响应结果的解析:

elasticsearch返回的结果是一个JSON字符串,结构包含:

hits:命中的结果

total:总条数,其中的value是具体的总条数值

max_score:所有结果中得分最高的文档的相关性算分

hits:搜索结果的文档数组,其中的每个文档都是一个json对象

_source:文档中的原始数据,也是json对象

因此,我们解析响应结果,就是逐层解析JSON字符串,流程如下:

SearchHits:通过response.getHits()获取,就是JSON中的最外层的hits,代表命中的结果

SearchHits#getTotalHits().value:获取总条数信息

SearchHits#getHits():获取SearchHit数组,也就是文档数组

SearchHit#getSourceAsString():获取文档结果中的_source,也就是原始的json文档数据

3.1.3 完整代码

完整代码如下:

@Test

void testMatchAll() throws IOException {

// 1.准备Request

SearchRequest request = new SearchRequest("hotel");

// 2.准备DSL

request.source()

.query(QueryBuilders.matchAllQuery());

// 3.发送请求

SearchResponse response = client.search(request, RequestOptions.DEFAULT);

// 4.解析响应

handleResponse(response);

}

private void handleResponse(SearchResponse response) {

// 4.解析响应

SearchHits searchHits = response.getHits();

// 4.1.获取总条数

long total = searchHits.getTotalHits().value;

System.out.println("共搜索到" + total + "条数据");

// 4.2.文档数组

SearchHit[] hits = searchHits.getHits();

// 4.3.遍历

for (SearchHit hit : hits) {

// 获取文档source

String json = hit.getSourceAsString();

// 反序列化

HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);

System.out.println("hotelDoc = " + hotelDoc);

}

}

3.2 设置查询条件

3.2.1 全文检索查询

全文检索的match和multi_match查询与match_all的API基本一致。差别是查询条件,也就是query的部分。

因此,Java代码上的差异主要是request.source().query()中的参数了。同样是利用QueryBuilders提供的方法:

而结果解析代码则完全一致,可以抽取并共享。

完整代码如下:

@Test

void testMatch() throws IOException {

// 1.准备Request

SearchRequest request = new SearchRequest("hotel");

// 2.准备DSL

request.source()

.query(QueryBuilders.matchQuery("all", "如家"));

// 3.发送请求

SearchResponse response = client.search(request, RequestOptions.DEFAULT);

// 4.解析响应

handleResponse(response);

}

3.2.2 精准查询

精确查询主要是两者:

term:词条精确匹配

range:范围查询

与之前的查询相比,差异同样在查询条件,其它都一样。

查询条件构造的API如下:

3.2.3 地理查询

DSL格式

在cn.itcast.hotel.service.impl的HotelService的search方法中,添加一个排序功能:

完整代码:

@Override

public PageResult search(RequestParams params) {

try {

// 1.准备Request

SearchRequest request = new SearchRequest("hotel");

// 2.准备DSL

// 2.1.query

buildBasicQuery(params, request);

// 2.2.分页

int page = params.getPage();

int size = params.getSize();

request.source().from((page - 1) * size).size(size);

// 2.3.排序

String location = params.getLocation();

if (location != null && !location.equals("")) {

request.source().sort(SortBuilders

.geoDistanceSort("location", new GeoPoint(location))

.order(SortOrder.ASC)

.unit(DistanceUnit.KILOMETERS)

);

}

// 3.发送请求

SearchResponse response = client.search(request, RequestOptions.DEFAULT);

// 4.解析响应

return handleResponse(response);

} catch (IOException e) {

throw new RuntimeException(e);

}

}

3.2.4 布尔查询

布尔查询是用must、must_not、filter等方式组合其它查询,代码示例如下:

可以看到,API与其它查询的差别同样是在查询条件的构建,QueryBuilders,结果解析等其他代码完全不变。

完整代码如下:

@Test

void testBool() throws IOException {

// 1.准备Request

SearchRequest request = new SearchRequest("hotel");

// 2.准备DSL

// 2.1.准备BooleanQuery

BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

// 2.2.添加term

boolQuery.must(QueryBuilders.termQuery("city", "杭州"));

// 2.3.添加range

boolQuery.filter(QueryBuilders.rangeQuery("price").lte(250));

request.source().query(boolQuery);

// 3.发送请求

SearchResponse response = client.search(request, RequestOptions.DEFAULT);

// 4.解析响应

handleResponse(response);

}

3.2.5 算分函数查询

java代码逻辑:添加一个isAD字段,在算分函数的filter中判断isAD=ture就进行重新算分

function_score查询结构如下:

对应的JavaAPI如下:

我们可以将之前写的boolean查询作为原始查询条件放到query中,接下来就是添加过滤条件、算分函数、加权模式了。

// 算分控制

FunctionScoreQueryBuilder functionScoreQuery =

QueryBuilders.functionScoreQuery(

// 原始查询,相关性算分的查询

boolQuery,

// function score的数组

new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{

// 其中的一个function score 元素

new FunctionScoreQueryBuilder.FilterFunctionBuilder(

// 过滤条件

QueryBuilders.termQuery("isAD", true),

// 算分函数

ScoreFunctionBuilders.weightFactorFunction(10)

)

});

//将查询请求放入查询

request.source().query(functionScoreQuery);

3.3 设置搜索结果

3.3.1 排序和分页

由于这两个比较简单,所以一起写了

搜索结果的排序和分页是与query同级的参数,因此同样是使用request.source()来设置。

对应的API如下:

完整代码示例:

@Test

void testPageAndSort() throws IOException {

// 页码,每页大小

int page = 1, size = 5;

// 1.准备Request

SearchRequest request = new SearchRequest("hotel");

// 2.准备DSL

// 2.1.query

request.source().query(QueryBuilders.matchAllQuery());

// 2.2.排序 sort

request.source().sort("price", SortOrder.ASC);

// 2.3.分页 from、size

request.source().from((page - 1) * size).size(5);

// 3.发送请求

SearchResponse response = client.search(request, RequestOptions.DEFAULT);

// 4.解析响应

handleResponse(response);

}

3.3.2 高亮

高亮的代码与之前代码差异较大,有两点:

查询的DSL:其中除了查询条件,还需要添加高亮条件,同样是与query同级。

结果解析:结果除了要解析_source文档数据,还要解析高亮结果

1)高亮请求构建

高亮请求的构建API如下:

上述代码省略了查询条件部分,但是大家不要忘了:高亮查询必须使用全文检索查询,并且要有搜索关键字,将来才可以对关键字高亮。

完整代码如下:

@Test

void testHighlight() throws IOException {

// 1.准备Request

SearchRequest request = new SearchRequest("hotel");

// 2.准备DSL

// 2.1.query

request.source().query(QueryBuilders.matchQuery("all", "如家"));

// 2.2.高亮

request.source().highlighter(new HighlightBuilder().field("name").requireFieldMatch(false));

// 3.发送请求

SearchResponse response = client.search(request, RequestOptions.DEFAULT);

// 4.解析响应

handleResponse(response);

}

2)高亮结果解析

高亮的结果与查询的文档结果默认是分离的,并不在一起。

因此解析高亮的代码需要额外处理:

代码解读:

第一步:从结果中获取source。hit.getSourceAsString(),这部分是非高亮结果,json字符串。还需要反序列为HotelDoc对象

第二步:获取高亮结果。hit.getHighlightFields(),返回值是一个Map,key是高亮字段名称,值是HighlightField对象,代表高亮值

第三步:从map中根据高亮字段名称,获取高亮字段值对象HighlightField

第四步:从HighlightField中获取Fragments,并且转为字符串。这部分就是真正的高亮字符串了

第五步:用高亮的结果替换HotelDoc中的非高亮结果

完整代码如下:

private void handleResponse(SearchResponse response) {

// 4.解析响应

SearchHits searchHits = response.getHits();

// 4.1.获取总条数

long total = searchHits.getTotalHits().value;

System.out.println("共搜索到" + total + "条数据");

// 4.2.文档数组

SearchHit[] hits = searchHits.getHits();

// 4.3.遍历

for (SearchHit hit : hits) {

// 获取文档source

String json = hit.getSourceAsString();

// 反序列化

HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);

// 获取高亮结果

Map highlightFields = hit.getHighlightFields();

if (!CollectionUtils.isEmpty(highlightFields)) {

// 根据字段名获取高亮结果

HighlightField highlightField = highlightFields.get("name");

if (highlightField != null) {

// 获取高亮值

String name = highlightField.getFragments()[0].string();

// 覆盖非高亮结果

hotelDoc.setName(name);

}

}

System.out.println("hotelDoc = " + hotelDoc);

}

}

3.3.3 聚合

聚合条件与query条件同级别,因此需要使用request.source()来指定聚合条件。

聚合条件的语法:

聚合的结果也与查询结果不同,API也比较特殊。不过同样是JSON逐层解析:

举例:业务代码

@Override

public Map> filters(RequestParams params) {

try {

// 1.准备Request

SearchRequest request = new SearchRequest("hotel");

// 2.准备DSL

// 2.1.query查询语句

buildBasicQuery(params, request);

// 2.2.设置size

request.source().size(0);

// 2.3.聚合

buildAggregation(request);

// 3.发出请求

SearchResponse response = client.search(request, RequestOptions.DEFAULT);

// 4.解析结果

Map> result = new HashMap<>();

Aggregations aggregations = response.getAggregations();

// 4.1.根据品牌名称,获取品牌结果

List brandList = getAggByName(aggregations, "brandAgg");

result.put("品牌", brandList);

// 4.2.根据品牌名称,获取品牌结果

List cityList = getAggByName(aggregations, "cityAgg");

result.put("城市", cityList);

// 4.3.根据品牌名称,获取品牌结果

List starList = getAggByName(aggregations, "starAgg");

result.put("星级", starList);

return result;

} catch (IOException e) {

throw new RuntimeException(e);

}

}

private void buildAggregation(SearchRequest request) {

request.source().aggregation(AggregationBuilders

.terms("brandAgg")

.field("brand")

.size(100)

);

request.source().aggregation(AggregationBuilders

.terms("cityAgg")

.field("city")

.size(100)

);

request.source().aggregation(AggregationBuilders

.terms("starAgg")

.field("starName")

.size(100)

);

}

private List getAggByName(Aggregations aggregations, String aggName) {

// 4.1.根据聚合名称获取聚合结果

Terms brandTerms = aggregations.get(aggName);

// 4.2.获取buckets

List buckets = brandTerms.getBuckets();

// 4.3.遍历

List brandList = new ArrayList<>();

for (Terms.Bucket bucket : buckets) {

// 4.4.获取key

String key = bucket.getKeyAsString();

brandList.add(key);

}

return brandList;

}

自动补全

① 设置创建索引库(设置一个自动补全字段,类型为:completion)

② 重新插入数据

③ 查询(查询时要设置这个自动补全操作的名称,并且指定那个类型为completion的字段)

④ 分解结果(结果也需要根据之前设置这个自动查询操作的名称来取)

当用户在搜索框输入字符时,我们应该提示出与该字符有关的搜索项,如图:

这种根据用户输入的字母,提示完整词条的功能,就是自动补全了。

1. 拼音分词器

下载拼音分词器记得版本要和ES对应,不对应会报错

要实现根据字母做补全,就必须对文档按照拼音分词。在GitHub上恰好有elasticsearch的拼音分词插件。地址:https://github.com/medcl/elasticsearch-analysis-pinyin

课前资料中也提供了拼音分词器的安装包:

安装方式与IK分词器一样,分三步:

​ ①解压

​ ②上传到虚拟机中,elasticsearch的plugin目录

​ ③重启elasticsearch

​ ④测试

详细安装步骤可以参考IK分词器的安装过程。

2. 自定义拼音分词器

如何使用拼音分词器?

①下载pinyin分词器

②解压并放到elasticsearch的plugin目录

③重启即可

如何自定义分词器?

①创建索引库时,在settings中配置,可以包含三部分

②character filter

③tokenizer

④filter

拼音分词器注意事项?

为了避免搜索到同音字,搜索时不要使用拼音分词器

默认的拼音分词器会将每个汉字单独分为拼音,而我们希望的是每个词条形成一组拼音,需要对拼音分词器做个性化定制,形成自定义分词器。官网文档查询地址:https://github.com/medcl/elasticsearch-analysis-pinyin

elasticsearch中分词器(analyzer)的组成包含三部分:

character filters:在tokenizer之前对文本进行处理。例如删除字符、替换字符

tokenizer:将文本按照一定的规则切割成词条(term)。例如keyword,就是不分词;还有ik_smart

tokenizer filter:将tokenizer输出的词条做进一步处理。例如大小写转换、同义词处理、拼音处理等

文档分词时会依次由这三部分来处理文档:

声明自定义分词器的语法如下:

PUT /test

{

"settings": {

"analysis": {

"analyzer": { // 自定义分词器

"my_analyzer": {  // 分词器名称

"tokenizer": "ik_max_word",

"filter": "py"

}

},

"filter": {  // 自定义tokenizer filter

"py": { // 过滤器名称

"type": "pinyin", // 过滤器类型,这里是pinyin

"keep_full_pinyin": false,

"keep_joined_full_pinyin": true,

"keep_original": true,

"limit_first_letter_length": 16,

"remove_duplicated_term": true,

"none_chinese_pinyin_tokenize": false

}

}

}

},

"mappings": {

"properties": {

"name": {

"type": "text",

"analyzer": "my_analyzer",

"search_analyzer": "ik_smart"

}

}

}

}

测试:

3. 自动补全查询

三步骤:

① 创建索引库

② 插入数据

③ 查询的DSL语句

elasticsearch提供了Completion Suggester查询来实现自动补全功能。这个查询会匹配以用户输入内容开头的词条并返回。为了提高补全查询的效率,对于文档中字段的类型有一些约束:

参与补全查询的字段必须是completion类型。

字段的内容一般是用来补全的多个词条形成的数组。

比如,一个这样的索引库:

// 创建索引库

PUT test

{

  "mappings": {

    "properties": {

      "title":{

        "type": "completion"

      }

    }

  }

}

然后插入下面的数据:

// 示例数据

POST test/_doc

{

  "title": ["Sony", "WH-1000XM3"]

}

POST test/_doc

{

  "title": ["SK-II", "PITERA"]

}

POST test/_doc

{

  "title": ["Nintendo", "switch"]

}

查询的DSL语句如下:

// 自动补全查询

GET /test/_search

{

  "suggest": {

    "title_suggest": { //设置这个自动查询操作的名称

      "text": "s", // 关键字

      "completion": {

        "field": "title", // 补全查询的字段名

        "skip_duplicates": true, // 跳过重复的

        "size": 10 // 获取前10条结果

      }

    }

  }

}

4. 自动补全嵌入项目

4.1 修改索引库映射结构

重点注意:

① all、name字段等要 分词设置为自定义分词器("analyzer": "text_anlyzer")(一般要分词,然后再对分词后的词语进行拼音处理),查询设置为最精简分词器("search_analyzer": "ik_smart")

② 设置一个自动补全字段(如 suggestion) 类型必须为:completion,并且使用自定义分词器(一般不分词直接对整个词语进行拼音处理)

先删除之前的索引库,再设置如下:

// 酒店数据索引库

PUT /hotel

{

"settings": {

"analysis": {

"analyzer": {

"text_anlyzer": {

"tokenizer": "ik_max_word",

"filter": "py"

},

"completion_analyzer": {

"tokenizer": "keyword",

"filter": "py"

}

},

"filter": {

"py": {

"type": "pinyin",

"keep_full_pinyin": false,

"keep_joined_full_pinyin": true,

"keep_original": true,

"limit_first_letter_length": 16,

"remove_duplicated_term": true,

"none_chinese_pinyin_tokenize": false

}

}

}

},

"mappings": {

"properties": {

"id":{

"type": "keyword"

},

"name":{

"type": "text",

"analyzer": "text_anlyzer",

"search_analyzer": "ik_smart",

"copy_to": "all"

},

"address":{

"type": "keyword",

"index": false

},

"price":{

"type": "integer"

},

"score":{

"type": "integer"

},

"brand":{

"type": "keyword",

"copy_to": "all"

},

"city":{

"type": "keyword"

},

"starName":{

"type": "keyword"

},

"business":{

"type": "keyword",

"copy_to": "all"

},

"location":{

"type": "geo_point"

},

"pic":{

"type": "keyword",

"index": false

},

"all":{

"type": "text",

"analyzer": "text_anlyzer",

"search_analyzer": "ik_smart"

},

"suggestion":{

"type": "completion",

"analyzer": "completion_analyzer"

}

}

}

}

4.2 修改实体类

类型为completion的字段需要在改造方法里做组装

HotelDoc中要添加一个字段,用来做自动补全,内容可以是酒店品牌、城市、商圈等信息。按照自动补全字段的要求,最好是这些字段的数组。

因此我们在HotelDoc中添加一个suggestion字段,类型为List,然后将brand、city、business等信息放到里面。

代码如下:

package cn.itcast.hotel.pojo;

import lombok.Data;

import lombok.NoArgsConstructor;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.Collections;

import java.util.List;

@Data

@NoArgsConstructor

public class HotelDoc {

private Long id;

private String name;

private String address;

private Integer price;

private Integer score;

private String brand;

private String city;

private String starName;

private String business;

private String location;

private String pic;

private Object distance;

private Boolean isAD;

private List suggestion;

public HotelDoc(Hotel hotel) {

this.id = hotel.getId();

this.name = hotel.getName();

this.address = hotel.getAddress();

this.price = hotel.getPrice();

this.score = hotel.getScore();

this.brand = hotel.getBrand();

this.city = hotel.getCity();

this.starName = hotel.getStarName();

this.business = hotel.getBusiness();

this.location = hotel.getLatitude() + ", " + hotel.getLongitude();

this.pic = hotel.getPic();

// 组装suggestion

if(this.business.contains("/")){

// business有多个值,需要切割

String[] arr = this.business.split("/");

// 添加元素

this.suggestion = new ArrayList<>();

this.suggestion.add(this.brand);

Collections.addAll(this.suggestion, arr);

}else {

this.suggestion = Arrays.asList(this.brand, this.business);

}

}

}

4.3 重新导入数据

先删除数据,再重新执行之前编写的导入数据功能,可以看到新的酒店数据中包含了suggestion:

4.4 自动补全的JavaAPI

示例:(这两幅图有点乱,看不懂就忽略)

查询代码如下:

解析结果代码如下:

1)在cn.itcast.hotel.web包下的HotelController中添加新接口,接收新的请求:

@GetMapping("suggestion")

public List getSuggestions(@RequestParam("key") String prefix) {

return hotelService.getSuggestions(prefix);

}

2)在cn.itcast.hotel.service包下的IhotelService中添加方法:

List getSuggestions(String prefix);

3)在cn.itcast.hotel.service.impl.HotelService中实现该方法:

@Override

public List getSuggestion(String prefix) {

try {

// 1.准备Request

SearchRequest request = new SearchRequest("hotel");

// 2.准备DSL

request.source().suggest(new SuggestBuilder().addSuggestion(

"hotelSuggestion", //设置这个自动补全操作的名称

SuggestBuilders.completionSuggestion("suggestion") //类型为completion的字段名

.prefix(prefix)

.skipDuplicates(true)

.size(10)

));

// 3.发起请求

SearchResponse response = client.search(request, RequestOptions.DEFAULT);

// 4.解析结果

Suggest suggest = response.getSuggest();

// 4.1.根据补全查询名称,获取补全结果(这里的参数是索引库里类型为completion的字段名)

CompletionSuggestion suggestions = suggest.getSuggestion("hotelSuggestion"); //之前设置的这个自动查询操作的名称

// 4.2.获取options

List options = suggestions.getOptions();

// 4.3.遍历

List list = new ArrayList<>(options.size());

for (CompletionSuggestion.Entry.Option option : options) {

String text = option.getText().toString();

list.add(text);

}

return list;

} catch (IOException e) {

throw new RuntimeException(e);

}

}

ES与Mysql数据同步

elasticsearch中的酒店数据来自于mysql数据库,因此mysql数据发生改变时,elasticsearch也必须跟着改变,这个就是elasticsearch与mysql之间的数据同步。

1. 三种方法

常见的数据同步方案有三种:

同步调用

异步通知

监听binlog

方式一:同步调用

优点:实现简单,粗暴

缺点:业务耦合度高

方式二:异步通知【常用】

优点:低耦合,实现难度一般

缺点:依赖mq的可靠性

方式三:监听binlog

优点:完全解除服务间耦合

缺点:开启binlog增加数据库负担、实现复杂度高

1.1.同步调用

方案一:同步调用

基本步骤如下:

hotel-demo对外提供接口,用来修改elasticsearch中的数据

酒店管理服务在完成数据库操作后,直接调用hotel-demo提供的接口,

1.2.异步通知

方案二:异步通知

流程如下:

hotel-admin对mysql数据库数据完成增、删、改后,发送MQ消息

hotel-demo监听MQ,接收到消息后完成elasticsearch数据修改

1.3.监听binlog

方案三:监听binlog

流程如下:

给mysql开启binlog功能

mysql完成增、删、改操作都会记录在binlog中

hotel-demo基于canal监听binlog变化,实时更新elasticsearch中的内容

2. 实现数据同步

当数据发生增、删、改时,要求对elasticsearch中数据也要完成相同操作。

步骤:

单机部署并启动MQ(单机部署在MQ部分有讲)

接收者中声明exchange、queue、RoutingKey

在hotel-admin发送者中的增、删、改业务中完成消息发送

在hotel-demo接收者中完成消息监听,并更新elasticsearch中数据

启动并测试数据同步功能

2.0 导入依赖和yaml

对发送者和消费者都添加依赖和yaml信息

1)引入依赖

org.springframework.boot

spring-boot-starter-amqp

2)yaml

spring:

rabbitmq: #MQ配置

host: 192.168.194.131 # 主机名

port: 5672 # 端口

virtual-host: / # 虚拟主机

username: itcast # 用户名

password: 123321 # 密码

2.1 声明交换机、队列

MQ结构如图:

1)声明队列交换机名称

在hotel-admin发送者和hotel-demo消费者中的cn.itcast.hotel.constatnts包下新建一个类MqConstants:

package cn.itcast.hotel.constatnts;

public class MqConstants {

/**

* 交换机

*/

public final static String HOTEL_EXCHANGE = "hotel.topic";

/**

* 监听新增和修改的队列

*/

public final static String HOTEL_INSERT_QUEUE = "hotel.insert.queue";

/**

* 监听删除的队列

*/

public final static String HOTEL_DELETE_QUEUE = "hotel.delete.queue";

/**

* 新增或修改的RoutingKey

*/

public final static String HOTEL_INSERT_KEY = "hotel.insert";

/**

* 删除的RoutingKey

*/

public final static String HOTEL_DELETE_KEY = "hotel.delete";

}

2)声明队列交换机

在hotel-demo消费者中,定义配置类,声明队列、交换机:

package cn.itcast.hotel.config;

import cn.itcast.hotel.constants.MqConstants;

import org.springframework.amqp.core.Binding;

import org.springframework.amqp.core.BindingBuilder;

import org.springframework.amqp.core.Queue;

import org.springframework.amqp.core.TopicExchange;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

@Configuration

public class MqConfig {

@Bean

public TopicExchange topicExchange(){

return new TopicExchange(MqConstants.HOTEL_EXCHANGE, true, false);

}

@Bean

public Queue insertQueue(){

return new Queue(MqConstants.HOTEL_INSERT_QUEUE, true);

}

@Bean

public Queue deleteQueue(){

return new Queue(MqConstants.HOTEL_DELETE_QUEUE, true);

}

@Bean

public Binding insertQueueBinding(){

return BindingBuilder.bind(insertQueue()).to(topicExchange()).with(MqConstants.HOTEL_INSERT_KEY);

}

@Bean

public Binding deleteQueueBinding(){

return BindingBuilder.bind(deleteQueue()).to(topicExchange()).with(MqConstants.HOTEL_DELETE_KEY);

}

}

2.2 发送MQ消息

在hotel-admin发送者中的增、删、改业务中分别发送MQ消息:

2.3 接收MQ消息

hotel-demo接收到MQ消息要做的事情包括:

新增消息:根据传递的hotel的id查询hotel信息,然后新增一条数据到索引库

删除消息:根据传递的hotel的id删除索引库中的一条数据

1)写SDL业务

首先在hotel-demo的cn.itcast.hotel.service包下的IHotelService中新增新增、删除业务

void deleteById(Long id);

void insertById(Long id);

给hotel-demo中的cn.itcast.hotel.service.impl包下的HotelService中实现业务:

@Override

public void deleteById(Long id) {

try {

// 1.准备Request

DeleteRequest request = new DeleteRequest("hotel", id.toString());

// 2.发送请求

client.delete(request, RequestOptions.DEFAULT);

} catch (IOException e) {

throw new RuntimeException(e);

}

}

@Override

public void insertById(Long id) {

try {

// 0.根据id查询酒店数据

Hotel hotel = getById(id);

// 转换为文档类型

HotelDoc hotelDoc = new HotelDoc(hotel);

// 1.准备Request对象

IndexRequest request = new IndexRequest("hotel").id(hotel.getId().toString());

// 2.准备Json文档

request.source(JSON.toJSONString(hotelDoc), XContentType.JSON);

// 3.发送请求

client.index(request, RequestOptions.DEFAULT);

} catch (IOException e) {

throw new RuntimeException(e);

}

}

2)编写监听器

在hotel-demo中的cn.itcast.hotel.mq包新增一个类:

package cn.itcast.hotel.mq;

import cn.itcast.hotel.constants.MqConstants;

import cn.itcast.hotel.service.IHotelService;

import org.springframework.amqp.rabbit.annotation.RabbitListener;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;

@Component

public class HotelListener {

@Autowired

private IHotelService hotelService;

/**

* 监听酒店新增或修改的业务

* @param id 酒店id

*/

@RabbitListener(queues = MqConstants.HOTEL_INSERT_QUEUE)

public void listenHotelInsertOrUpdate(Long id){

hotelService.insertById(id);

}

/**

* 监听酒店删除的业务

* @param id 酒店id

*/

@RabbitListener(queues = MqConstants.HOTEL_DELETE_QUEUE)

public void listenHotelDelete(Long id){

hotelService.deleteById(id);

}

}

2.4 测试

用postman调用增加/删除/修改mysql数据库的接口,然后去页面搜索看看删除的数据还是否能查到,或者修改/增加的数据能不能查出来

ES集群

1. 搭建ES集群

1.1 创建ES集群

部署es集群可以直接使用docker-compose来完成,不过要求你的Linux虚拟机至少有4G的内存空间

首先编写一个docker-compose文件,内容如下:

version: '2.2'

services:

es01:

image: docker.elastic.co/elasticsearch/elasticsearch:7.12.1

container_name: es01

environment:

- node.name=es01

- cluster.name=es-docker-cluster

- discovery.seed_hosts=es02,es03

- cluster.initial_master_nodes=es01,es02,es03

- bootstrap.memory_lock=true

- "ES_JAVA_OPTS=-Xms512m -Xmx512m"

ulimits:

memlock:

soft: -1

hard: -1

volumes:

- data01:/usr/share/elasticsearch/data

ports:

- 9200:9200

networks:

- elastic

es02:

image: docker.elastic.co/elasticsearch/elasticsearch:7.12.1

container_name: es02

environment:

- node.name=es02

- cluster.name=es-docker-cluster

- discovery.seed_hosts=es01,es03

- cluster.initial_master_nodes=es01,es02,es03

- bootstrap.memory_lock=true

- "ES_JAVA_OPTS=-Xms512m -Xmx512m"

ulimits:

memlock:

soft: -1

hard: -1

volumes:

- data02:/usr/share/elasticsearch/data

networks:

- elastic

es03:

image: docker.elastic.co/elasticsearch/elasticsearch:7.12.1

container_name: es03

environment:

- node.name=es03

- cluster.name=es-docker-cluster

- discovery.seed_hosts=es01,es02

- cluster.initial_master_nodes=es01,es02,es03

- bootstrap.memory_lock=true

- "ES_JAVA_OPTS=-Xms512m -Xmx512m"

ulimits:

memlock:

soft: -1

hard: -1

volumes:

- data03:/usr/share/elasticsearch/data

networks:

- elastic

volumes:

data01:

driver: local

data02:

driver: local

data03:

driver: local

networks:

elastic:

driver: bridge

es运行需要修改一些linux系统权限,修改/etc/sysctl.conf文件

vi /etc/sysctl.conf

添加下面的内容:

vm.max_map_count=262144

然后执行命令,让配置生效:

sysctl -p

通过docker-compose启动集群:

docker-compose up -d

1.2 集群状态监控

kibana可以监控es集群,不过新版本需要依赖es的x-pack 功能,配置比较复杂。

这里推荐使用cerebro来监控es集群状态,官方网址:https://github.com/lmenezes/cerebro

课前资料已经提供了安装包:

解压即可使用,非常方便。

解压好的目录如下:

进入对应的bin目录:

双击其中的cerebro.bat文件即可启动服务。

访问http://localhost:9000 即可进入管理界面:

输入你的elasticsearch的任意节点的地址和端口,点击connect即可:

绿色的条,代表集群处于绿色(健康状态)。

1.3创建索引库

创建索引库的时候需要设置分片数量(其他还有多少个ES服务在该集群)以及副本数量(本服务的数据拷贝几份)

方法一:利用kibana的DevTools创建索引库

如果没有启动ES的可视化界面Kibana,那就用方法二

在DevTools中输入指令:

PUT /itcast

{

"settings": {

"number_of_shards": 3, // 分片数量

"number_of_replicas": 1 // 副本数量

},

"mappings": {

"properties": {

// mapping映射定义 ...

}

}

}

方法二:利用cerebro创建索引库

利用cerebro还可以创建索引库:

填写索引库信息:

点击右下角的create按钮:

查看分片效果

回到首页,即可查看索引库分片效果:

2.集群脑裂问题

master eligible节点的作用是什么?

参与集群选主

主节点可以管理集群状态、管理分片信息、处理创建和删除索引库的请求

data节点的作用是什么?

数据的CRUD

coordinator节点的作用是什么?

路由请求到其它节点

合并查询到的结果,返回给用户

2.1.集群职责划分

通过改变配置文件中的 true——> false 来改变职责。如data数据职责节点就只保留data为true其他为false

注意:每个节点都是路由,这样可以保证不管哪个节点接收到请求可以分给其他人已经从其他人那接收信息。

elasticsearch中集群节点有不同的职责划分:

默认情况下,集群中的任何一个节点都同时具备上述四种角色。

但是真实的集群一定要将集群职责分离:(因为不同职责对CPU要求不同)

master节点:对CPU要求高,但是内存要求低

data节点:对CPU和内存要求都高

coordinating节点:对网络带宽、CPU要求高

职责分离可以让我们根据不同节点的需求分配不同的硬件去部署。而且避免业务之间的互相干扰。

一个典型的es集群职责划分如图:

2.2.脑裂问题

ES 7.0后默认配置了( eligible节点数量 + 1 )/ 2来解决脑裂问题

脑裂是因为集群中的节点失联导致的。

例如一个集群中,主节点与其它节点失联:

此时,node2和node3认为node1宕机,就会重新选主:

当node3当选后,集群继续对外提供服务,node2和node3自成集群,node1自成集群,两个集群数据不同步,出现数据差异。

当网络恢复后,因为集群中有两个master节点,集群状态的不一致,出现脑裂的情况:

解决脑裂的方案是,要求选票超过 ( eligible节点数量 + 1 )/ 2 才能当选为主,因此eligible节点数量最好是奇数。对应配置项是discovery.zen.minimum_master_nodes,在es7.0以后,已经成为默认配置,因此一般不会发生脑裂问题

例如:3个节点形成的集群,选票必须超过 (3 + 1) / 2 ,也就是2票。node3得到node2和node3的选票,当选为主。node1只有自己1票,没有当选。集群中依然只有1个主节点,没有出现脑裂。

3.集群分布式存储

当新增文档时,应该保存到不同分片,保证数据均衡,那么coordinating node如何确定数据该存储到哪个分片呢?

3.1.分片存储测试

插入三条数据:

测试可以看到,三条数据分别在不同分片:

结果:

3.2.分片存储原理

elasticsearch会通过hash算法来计算文档应该存储到哪个分片:

说明:

_routing默认是文档的id

算法与分片数量有关,因此索引库一旦创建,分片数量不能修改!

新增文档的流程如下:

解读:

1)新增一个id=1的文档

2)对id做hash运算,假如得到的是2,则应该存储到shard-2

3)shard-2的主分片在node3节点,将数据路由到node3

4)保存文档

5)同步给shard-2的副本replica-2,在node2节点

6)返回结果给coordinating-node节点

4. 集群分布式查询

原理:

elasticsearch的查询分成两个阶段:

scatter phase:分散阶段,coordinating node会把请求分发到每一个分片

gather phase:聚集阶段,coordinating node汇总data node的搜索结果,并处理为最终结果集返回给用户

5.集群故障转移

ES本身已经配置好了有集群故障转移,不需要我们再去配置

集群的master节点会监控集群中的节点状态,如果发现有节点宕机,会立即将宕机节点的分片数据迁移到其它节点,确保数据安全,这个叫做故障转移。

1)例如一个集群结构如图:

现在,node1是主节点,其它两个节点是从节点。

2)突然,node1发生了故障:

宕机后的第一件事,需要重新选主,例如选中了node2:

node2成为主节点后,会检测集群监控状态,发现:shard-1、shard-0没有副本节点。因此需要将node1上的数据迁移到node2、node3:

本文来自博客园,作者:不吃紫菜,遵循CC 4.0 BY-SA版权协议,

转载请附上原文出处链接:https://www.cnblogs.com/buchizicai/p/17093719.html及本声明;

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

posted @

2023-02-05 21:14 

不吃紫菜 

阅读(38735) 

评论(7) 

编辑 

收藏 

举报

会员力量,点亮园子希望

刷新页面返回顶部

公告

Copyright © 2024 不吃紫菜

Powered by .NET 8.0 on Kubernetes