当前位置: 首页 > 科技观察

如何在ASP.NETCore中集成ElasticSearch

时间:2023-03-16 11:00:19 科技观察

肯定会要求您向Web应用程序添加高级搜索功能,通常是类似Google的全文搜索。技术电子商务的发展过程中,要求我们让用户对产品进行超前研究,以便他们能够高效、完整地找到他们要找的东西。我们尝试了一种基于在对象的所有字段上搜索给定字符串的自定义搜索实现。为了优化时间,我们尝试在服务和数据库级别之间添加一个缓存层以避免对数据库造成太大压力,但我们对结果并不满意。然后我们在市场上寻找能够满足我们需求的第三方产品,经过深入分析,我们选择了采用ElasticSearch:一个分布式的、易适配的基于REST协议的搜索引擎,管理研究和分析,同时也是方便的数据外推和转换。具体来说,我们正在谈论一个基于ApacheLucene的开源全文搜索引擎,它可以用于管理文档的索引和研究。让我们尝试了解基本概念。ElasticSearch将数据存储在一个或多个索引中。ES的索引和SQLDB的索引非常相似,我们用它来存储和读取文档。文档是ElasticSearch世界中的主要实体。它由一组具有名称和一个或多个值的字段组成。每个文档可能有一组字段,并且没有给出模式或定义的结构。它只是一个JSON对象。所有文件在存储前都经过分析。此分析过程(称为映射)是通过过滤数据内容(例如删除HTML标签)并将其标记化以将文档拆分为标记来执行的。ElasticSearch中的每个文档都有一个类型。这使得可以在同一个索引上存储各种文档类型,并为几种类型获取多个映射。ElasticSearch服务器的单个实例称为节点。在许多情况下,单个节点就足够了,但有时您需要管理故障,或者您有太多数据无法使用单个节点进行管理。在这种情况下,您可以使用多节点集群,这是一组协同工作的节点来管理比单个实例可以处理的负载更大的负载。您可以配置您的集群,以便即使在某些节点不可用的情况下也能保证搜索和管理功能。为了使集群正常运行,ElasticSearch将数据分布到ApacheLucene中的多个物理索引中。这些索引称为“分片”,扩容过程称为“分片”。ElasticSearch自动管理分片,因此最终用户似乎只是一个大索引。副本是分片的副本,可用于以与原始分片相同的模式进行查询。副本卸载无法处理所有请求的单个节点上的负载,并提供更高的数据安全性,因为如果您丢失原始分片中的数据,它可以在副本上恢复。ElasticSearch收集了大量关于集群状态、索引设置的信息并将它们存储到网关中。在结构上,ElasticSearch基于一些简单的关键概念:默认设置和值使默认配置足以开箱即用地使用ElasticSearch。它以分布式方式工作。节点自动成为集群的一部分,并且在设置期间,节点尝试加入集群。没有SPOF(单点故障)的P2P架构。节点自动连接到集群中的其他计算机以更改数据并相互监视;只需向集群添加新节点,就可以轻松扩展数据量和容量。在索引中组织数据没有任何限制。允许用户修改数据模型而不影响搜索;NRT(近实时)搜索和版本控制。由于其分布式特性,无法避免位于不同节点上的数据之间的延迟和差异。因此,它提供了版本控制机制。当ElasticSearch节点启动时,它使用多播(或单播,如果已配置)来查找同一集群中的其他节点并连接到它们。在一个集群中,一个节点被选为主节点。该节点负责管理集群状态和将分片分配给节点的过程。主节点读取集群状态,并在需要时启动恢复模式,该模式允许知道哪些分片可用并将其中一个分片指定为主要分片。这样,即使集群没有所有可用资源,它似乎也能正常工作。然后主节点查找重复的分片并将它们作为副本处理。在标准运行期间,主节点检查所有可用节点是否正常工作。如果其中之一在配置的时间范围内变得不可用,则该节点被认为已损坏并运行容错过程。容错的主要活动是平衡损坏节点的集群和分片,并分配一个新节点负责这些分片。然后,对于主分片的每次丢失,定义一个在可用副本中选择的新主分片。如前所述,ElasticSearch提供了一些APIREST,每个能够发送HTTP请求和接收HTTP响应的系统(大多数开发框架的所有浏览器和库)都可以使用这些API。ElasticSearch请求由一些包含的已定义URL发送。它最终成为JSON主体。响应也是一个JSON文档。ElasticSearch提供了四种索引数据的方式。1.IndexingAPI:它允许将文档发送到定义的索引;2.BulkAPI:允许通过HTTP协议发送多个文档;3.UDPBulkAPI:它允许通过任何协议发送多个文档(更快但更不可靠);4.插件:在节点上执行,它们从外部系统获取数据。重要的是要记住索引只在主分片上而不是它的副本上,所以如果一个索引请求被发送到一个不包含主分片或可能包含它的副本的节点,请求将被转发到主分片。搜索是使用查询API执行的。使用QueryDSL(基于JSON的语言构建复杂查询),您可以:使用各种类型的查询,包括简单查询、短语、范围、布尔值、空间查询等;通过组合简单的查询来构建复杂的查询;通过排除不符合所选标准的文档而不影响其分数来过滤文档;查找与其他文档相似的文档;查找给定短语的建议或更正;查找与给定文档匹配的查询。搜索不是一个简单的单阶段过程,但是,它通常可以分为两个阶段:分散,查询索引的所有相关分片;聚集,那里都是有价值的结果。弄脏你的手!ES提供云和本地使用。如果你想在Windows机器上安装它,你需要有更新版本的Java虚拟机(https://www.elastic.co/support/matrix#matrix_jvm),然后可以将其作为zip文件下载来自ElasticSearch下载。页面(https://www.elastic.co/downloads/elasticsearch)并将其解压缩到磁盘上的文件夹,例如C:\Elasticsearch。要执行它,您可以运行C:\Elasticsearch\bin\elasticsearch.bat。如果您想将ElasticSearch作为一项服务使用,以便您可以使用Windows工具启动或停止它,您需要在文件C:\Elasticsearch\config\jvm.options中添加一行。对于32位系统,您必须键入-Xss320k*,对于64位系统,您必须键入-Xss1m。*更改此设置后,您必须打开命令提示符或Powershell并执行C:\Elasticsearch\bin\elasticsearch-service.bat。可用命令包括安装、删除、启动、停止和管理器。要创建服务,我们必须键入:C:\Elasticsearch\bin\elasticsearch-service.batinstall要管理服务,我们键入:C:\Elasticsearch\bin\elasticsearch-service.batmanager打开ElasticServiceManager,它是一个GUI,您可以通过它自定义有关服务的设置并管理其状态。默认情况下cluster.name和node.name分别是elasticsearch和你的主机名。如果您打算继续使用集群或添加更多节点,最好通过在elasticsearch.yml文件中修改这些默认值来将它们更改为唯一名称。我们可以通过浏览http://localhost:9200/来验证ElasicSearch是否正确执行。如果一切正常,我们将得到以下结果:为了实现基于.NETCore的解决方案,我们使用NEST包,可以使用以下命令安装它:dotnetaddpackageNESTNEST允许我们索引和搜索文档以及nodes和Admin在本地使用所有ElasticSearch功能。为了管理NEST插件,我们创建了ElasticsearchExtensions类:);(p=>p.Price).Ignore(p=>p.Quantity).Ignore(p=>p.Rating));}privatestaticvoidCreateIndex(IElasticClientclient,stringindexName){varcreateIndexResponse=client.Indices.Create(indexName,index=>index.Map(x=>x.AutoMap()));}}在其中我们找到对象的配置和映射,在本例中为Product类。在本课程中,我们决定在索引阶段忽略存储价格、数量和评级。使用以下指令在Startup.cs中调用此类:publicvoidConfigureServices(IServiceCollectionservices){//...services.AddElasticsearch(Configuration);}这使我们能够在启动时加载所有设置并在elasticsearch的appsettings.json文件中修改它们,我们在其中插入如下一行:"elasticsearch":{"index":"products","url":"http://localhost:9200/"}index表示默认选择用来存储文档的索引,url是我们的ElasticSearch实例的地址。我们的产品对象定义如下:;}公共字符串价格{得到;放;}publicint数量{get;放;}publicfloatRating{get;放;}publicDateTime发布日期{get;在我们的产品服务中,我们发现了两种方式:publicasyncTaskSaveSingleAsync(Productproduct){if(_cache.Any(p=>p.Id==product.Id)){await_elasticClient.UpdateAsync(product,u=>u.Doc(产品));}else{_cache.Add(产品);await_elasticClient.IndexDocumentAsync(产品);}}publicasyncTaskSaveManyAsync(产品[]产品){_cache.AddRange(产品);varresult=await_elasticClient.IndexManyAsync(产品);if(result.Errors){//theresponsecanbeinspectedforerrorsforeach(varitemWithErrorinresult.ItemsWithErrors){_logger.LogError("Failedtoindexdocument{0}:{1}",itemWithError.Id,itemWithError.Error);}}}publicasyncTaskSaveBulkAsync(Product[]products){_cache.AddRange(products);varresult=await_elasticClient.BulkAsync(b=>b.Index("products").IndexMany(products));if(result.Errors){//theresponsecanbeinspectedforerrorsforeach(varitemWithErrorinresult.ItemsWithErrors){_logger.LogError("Failedtoindexdocument{0}:{1}",itemWithError.Id,itemWithError.Error);}}}这里我们使用_cache数组来进一步缓存产品列表对于多模式我们还实现了批处理版本,这允许我们在更短的时间内索引大量文档,并且我们已经处理了日志插入任何错误。请注意,SaveSingleAsync方法通过检查缓存数组来管理文档插入和修改。对于文档删除,我们实现了DeleteAsync方法:publicasyncTaskDeleteAsync(Productproduct){await_elasticClient.DeleteAsync(product);if(_cache.Contains(product)){_cache.Remove(product);}}GetSearchUrl方法允许我们获取用于管理分页的URL。出于开发目的,我们实现了ReIndex方法,该方法允许我们删除索引中的所有文档,然后一次又一次地导入它们。这对于导入现有和卸载文档的列表很有用。//Onlyfordevelopmentpurpose[HttpGet("/search/reindex")]publicasyncTaskReIndex(){await_elasticClient.DeleteByQueryAsync(q=>q.MatchAll());varallProducts=(await_productService.GetProducts(int.MaxValue)).ToArray();foreach(varproductinallProducts){await_elasticClient.IndexDocumentAsync(product);}returnOk($"{allProducts.Length}product(s)reindexed");}出于示例目的,我们创建了一个允许我们添加的接口通过Bogus插件动态生成N个产品,并管理产品的增删改查。运行项目后,我们会看到如下画面:例如我们尝试添加10个产品到索引中,在文本框中输入10,点击ImportDocuments按钮,我们可以使用搜索框查看结果,也可以直接从浏览器浏览到http页面://localhost:9200/products/_search在那里我们将得到这样的结果:本文中使用的代码可在此处获得[2]。参考资料[1]查看原文:https://www.blexin.com/en-US/Article/Blog/How-to-integrate-ElasticSearch-in-ASPNET-Core-70[2]在这里获取:https://github.com/enricobencivenga/ElasticSearch