Elasticsearch集成到ASP.NET Core 3.1項目,CRUD操作示例


ElasticSearch簡介

ElasticSearch 是一個開源的搜索引擎,建立在一個全文搜索引擎庫 Apache Lucene™ 基礎之上。 Lucene 可以說是當下最先進、高性能、全功能的搜索引擎庫,無論是開源還是私有。

但是 Lucene 僅僅只是一個庫。為了充分發揮其功能,你需要使用 Java 並將 Lucene 直接集成到應用程序中。 更糟糕的是,您可能需要獲得信息檢索學位才能了解其工作原理。Lucene 非常 復雜。

ElasticSearch 也是使用 Java 編寫的,它的內部使用 Lucene 做索引與搜索,但是它的目的是使全文檢索變得簡單, 通過隱藏 Lucene 的復雜性,取而代之的提供一套簡單一致的 RESTful API。

然而,Elasticsearch 不僅僅是 Lucene,並且也不僅僅只是一個全文搜索引擎。 它可以被下面這樣准確的形容:

● 一個分布式的實時文檔存儲,每個字段 可以被索引與搜索
● 一個分布式實時分析搜索引擎
● 能勝任上百個服務節點的擴展,並支持 PB 級別的結構化或者非結構化數據

官方客戶端在Java、.NET、PHP、Python、Ruby、Nodejs和許多其他語言中都是可用的。根據 DB-Engines 的排名顯示,ElasticSearch 是最受歡迎的企業搜索引擎,其次是Apache Solr,也是基於Lucene。

 

ElasticSearch不支持的場景:

1、 不支持事務
2、 不支持多表關聯查詢業務
3、不適合頻繁更新的業務場景, 讀寫有一定延時,寫入的數據,最快1s能被檢索到
默認情況下每個分片會每秒自動刷新一次,也就是說文檔從Index請求到對外可見能夠被搜到,最少要1秒鍾,網絡和CPU再快也不行。這么做是Lucene為了提高寫操作的吞吐量而做出的延遲犧牲,當然這個設置是可以手動調整的,但是並不建議你去動它,會極大地影響搜索性能,刷新頻率太高也會導致集群陷入癱瘓。不同的應用對實時性的定義並不一樣,這取決於需求。

 

開始ElasticSearch之旅

1.創建 ASP.NET Core Web API 項目

創建net Core項目,將其命名為:ElasticSearchDemo,創建項目后,通過NuGet庫引入Nest包

 

 2.添加實體模型

將 ES.Models目錄添加到項目根目錄下

使用以下代碼將 FamousPoemsModel類添加到 ES.Models 目錄

using System;

namespace ES.Models
{
    /// <summary>
    /// 
    /// </summary>
    public class FamousPoemsModel
    {
        /// <summary>
        /// 
        /// </summary>
        public FamousPoemsModel()
        {

        }
        /// <summary>
        /// 
        /// </summary>
        public string Id { get; set; }
        /// <summary>
        /// 作者
        /// </summary>
        [Nest.Keyword]
        public string vcAuthor { get; set; }
        /// <summary>
        /// 內容
        /// </summary>
        [Nest.Keyword]
        public string vcContent { get; set; }
        /// <summary>
        /// 標題
        /// </summary>
        [Nest.Keyword]
        public string vcTitle { get; set; }
        /// <summary>
        /// 創建時間
        /// </summary>
        public DateTime dtCreateTime { get; set; }
        /// <summary>
        /// 更新時間
        /// </summary>
        public DateTime dtUpdateTime { get; set; }
    }
}

3.添加配置模型

appsettings.json 添加以下ElasticSearch配置

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ElasticSearch": {
    "Uri": "http://es-cn-zvp2asu64001ta726.public.elasticsearch.aliyuncs.com:9200",
    "UserName": "elastic",
    "Password": "es123456@"
  }
}

4.創建ES.Business目錄,在目錄下創建ElasticSearch、IService、Service目錄,廢話不多說,直接上代碼

using ES.Business.IService;
using ES.Core;
using ES.Models;
using Nest;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ES.Business.Service
{
    /// <summary>
    /// 
    /// </summary>
    public class FamousPoemsService : IFamousPoemsService, ITransientDependency
    {
        /// <summary>
        /// 
        /// </summary>
        private readonly IEsUpdateService _updateService;
        /// <summary>
        /// 
        /// </summary>
        private readonly IEsClientService _clientService;
        /// <summary>
        /// 
        /// </summary>
        private readonly IEsIndexService _indexService;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="updateService"></param>
        /// <param name="clientService"></param>
        /// <param name="indexService"></param>
        public FamousPoemsService(IEsUpdateService updateService, IEsClientService clientService, IEsIndexService indexService)
        {
            _updateService = updateService;
            _clientService = clientService;
            _indexService = indexService;
        }
        /// <summary>
        /// 刪除
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public async Task<long> DeleteAsync(string Id)
        {
            var mustFilters = new List<Func<QueryContainerDescriptor<FamousPoemsModel>, QueryContainer>>();
            mustFilters.Add(t => t.Match(m => m.Field(f => f.Id).Query(Id)));

            var result = await _clientService.Client.DeleteByQueryAsync<FamousPoemsModel>(x => x.Index("famouspoemsmodel")
            .Query(q => q.Bool(b => b.Must(mustFilters))));

            return result.Deleted;
        }
        /// <summary>
        /// 根據相關條件獲取分頁數據
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<PageModel<FamousPoemsModel>> GetPageAsync(ParameterModel dto)
        {
            PageModel<FamousPoemsModel> pageModel = new PageModel<FamousPoemsModel>();
            var mustFilters = new List<Func<QueryContainerDescriptor<FamousPoemsModel>, QueryContainer>>();

            if (!string.IsNullOrEmpty(dto.vcTitle))
            {
                mustFilters.Add(t => t.Match(m => m.Field(f => f.vcTitle).Query(dto.vcTitle)));
            }

            if (dto.authors.Count() > 0)
            {
                mustFilters.Add(t => t.Terms(m => m.Field(f => f.vcAuthor).Terms(dto.authors.ToArray())));
            }

            var total = await _clientService.Client.CountAsync<FamousPoemsModel>(x => x.Index("famouspoemsmodel")
             .Query(q => q.Bool(b => b.Must(mustFilters))));

            if (total.Count == 0)
            {
                return pageModel;
            }

            pageModel.nDataCount = Convert.ToInt32(total.Count);
            pageModel.nPageCount = (int)Math.Ceiling((double)pageModel.nDataCount / dto.nPageSize);
            dto.nPageIndex = ((dto.nPageIndex < 1 ? 1 : dto.nPageIndex) - 1) * dto.nPageSize;

            var data = await _clientService.Client.SearchAsync<FamousPoemsModel>(x => x.Index("famouspoemsmodel")
     .Query(q => q.Bool(b => b.Must(mustFilters))).Sort(s => s.Ascending(d => d.dtCreateTime)).From(dto.nPageIndex).Size(dto.nPageSize));

            pageModel.data = (List<FamousPoemsModel>)data.Documents;
            return pageModel;
        }
        /// <summary>
        /// 新增數據
        /// </summary>
        /// <param name="poems"></param>
        /// <returns></returns>
        public async Task<bool> InsertAsync(FamousPoemsModel poems)
        {
            return await _indexService.InsertAsync(poems);
        }
        /// <summary>
        /// 新增批量數據
        /// </summary>
        /// <param name="poems"></param>
        /// <returns></returns>
        public async Task<bool> InsertRangeAsync(List<FamousPoemsModel> poems)
        {
            return await _indexService.InsertRangeAsync(poems);
        }
        /// <summary>
        /// 通過主鍵局部更新數據
        /// </summary>
        /// <param name="nId"></param>
        /// <param name="vcTitle"></param>
        /// <returns></returns>
        public async Task<bool> UpdateAsync(string nId, string vcTitle)
        {
            FamousPoemsModel dto = new FamousPoemsModel();
            dto.vcTitle = vcTitle;
            dto.dtUpdateTime = DateTime.Now;
            var result = _updateService.Update<FamousPoemsModel>(nId, dto);
            return result.IsValid;
        }
        /// <summary>
        /// 通過條件批量局部更新某個字段數據
        /// </summary>
        /// <returns></returns>
        public async Task<bool> UpdateByAuthorAsync(string vcAuthor)
        {
            var mustFilters = new List<Func<QueryContainerDescriptor<FamousPoemsModel>, QueryContainer>>();
            mustFilters.Add(t => t.Match(m => m.Field(f => f.vcAuthor).Query(vcAuthor)));

            var result = await _clientService.Client.UpdateByQueryAsync<FamousPoemsModel>(q => q.Index("famouspoemsmodel")
   .Query(q => q.Bool(t => t.Must(mustFilters)))
.Script(script => script.Source("ctx._source.dtUpdateTime=" + DateTime.Now + ";")));

            return result.IsValid;

        }
    }
}

5.將以下代碼添加到 Startup.ConfigureServices

          #region ES配置
            services.AddEsService(options =>
            {
                options.Urls = Configuration["ElasticSearch:Uri"];
                options.UserName = Configuration["ElasticSearch:UserName"];
                options.Password = Configuration["ElasticSearch:Password"];
            });
            #endregion

6.添加控制器

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ES.Business.IService;
using ES.Models;
using ES.Util;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;

namespace ES.Web.Controllers
{
    /// <summary>
    /// 屬性注入
    /// </summary>
    public class PoemsController : ControllerBase
    {
        /// <summary>
        /// 
        /// </summary>
        public IFamousPoemsService famousPoemsService { get; set; }

        /// <summary>
        /// 插入單條數據
        /// </summary>
        /// <param name="poems"></param>
        /// <returns></returns>
        [HttpPost("Poems/InsertAsync")]
        public async Task<IActionResult> InsertAsync([FromBody]FamousPoemsModel poems)
        {
            return Content(JsonConvert.SerializeObject(await famousPoemsService.InsertAsync(poems)));
        }
        /// <summary>
        /// 批量插入數據
        /// </summary>
        /// <param name="poems"></param>
        /// <returns></returns>
        [HttpPost("Poems/InsertRangeAsync")]
        public async Task<ActionResult> InsertRangeAsync([FromBody]List<FamousPoemsModel> poems)
        {
            return Content(JsonConvert.SerializeObject(await famousPoemsService.InsertRangeAsync(poems)));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        [HttpPost("Poems/DeleteAsync")]
        public async Task<ActionResult> DeleteAsync(string Id)
        {
            return Content(JsonConvert.SerializeObject(await famousPoemsService.DeleteAsync(Id)));
        }
        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="Id"></param>
        /// <param name="vcTitle"></param>
        /// <returns></returns>
        [HttpPost("Poems/UpdateAsync")]
        public async Task<ActionResult> UpdateAsync(string Id, string vcTitle)
        {
            return Content(JsonConvert.SerializeObject(await famousPoemsService.UpdateAsync(Id, vcTitle)));
        }
        /// <summary>
        /// 批量更新
        /// </summary>
        /// <param name="vcAuthor"></param>
        /// <returns></returns>
        [HttpPost("Poems/UpdateByAuthorAsync")]
        public async Task<ActionResult> UpdateByAuthorAsync(string vcAuthor)
        {
           
            return Content(JsonConvert.SerializeObject(await famousPoemsService.UpdateByAuthorAsync(vcAuthor)));
        }
        /// <summary>
        /// 根據相關條件獲取分頁數據
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [ProducesResponseType(typeof(FamousPoemsModel), 200)]
        [HttpPost("Poems/GetPageAsync")]
        public async Task<ActionResult> GetPageAsync([FromBody]ParameterModel dto)
        {
            return Content(JsonConvert.SerializeObject(await famousPoemsService.GetPageAsync(dto)));
        }
    }
}

 

本示例代碼gitee地址:https://gitee.com/fan_zhongtuan/elasticsearchdemo.git

阿里雲ElasticSearch新用戶0員免費試用地址:https://www.aliyun.com/product/bigdata/elasticsearch

Elasticsearch官方權威文檔:https://www.elastic.co/guide/cn/elasticsearch/guide/current/foreword_id.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM