NETCORE - ElasticSearch 搜索服务

 NETCORE - ElasticSearch 搜索服务

相关文档地址

Elasticsearch文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html

Elasticsearch.Net和Nest官方文档:https://www.elastic.co/guide/en/elasticsearch/client/net-api/7.x/index.html

 

前提:搭建 ElasticSearch 环境

  参考:https://www.cnblogs.com/1285026182YUAN/p/16719050.html 

 

创建项目 NETCORE.TestElasticsearch

环境:NetCore 6 ,web api 项目

 

 

 

 

 1. 安装 Nuget 包

  Elasticsearch.Net 和 Nest

 

2.  增加配置文件 appsettings.json

  "EsConfig": {
    "ConnectionStrings": [ "http://127.0.0.1:9200/" ]
  }

 

  

3. 创建配置类 EsConfig.cs

using Microsoft.Extensions.Options;
namespace NETCORE.TestElasticsearch
{
    public class EsConfig : IOptions<EsConfig>
    {
        public List<string> Urls { get; set; }
        public EsConfig Value => this;
    }
}

 

 

4. 创建ElasticSearch提供者接口类 IEsClientProvider.cs

using Nest;
namespace NETCORE.TestElasticsearch.ESPackage
{
    /// <summary>
    /// ElasticClient 提供者接口
    /// </summary>
    public interface IEsClientProvider
    {
        /// <summary>
        /// 获取ElasticClient
        /// </summary>
        /// <returns></returns> 
        ElasticClient GetClient();
        /// <summary>
        /// 指定index获取ElasticClient
        /// </summary>
        /// <param name="indexName"></param>
        /// <returns></returns>
        ElasticClient GetClient(string indexName);
    }
}

 

 

5. 创建 ElasticSearch 提供者实体类 EsClientProvider.cs

using Elasticsearch.Net;
using Microsoft.Extensions.Options;
using Nest;

namespace NETCORE.TestElasticsearch.ESPackage
{


    /// <summary>
    /// ElasticClient提供者
    /// </summary>
    public class EsClientProvider : IEsClientProvider
    {
        private readonly IOptions<EsConfig> _EsConfig;
        public EsClientProvider(IOptions<EsConfig> esConfig)
        {
            _EsConfig = esConfig;
        }
        /// <summary>
        /// 获取elastic client  
        /// </summary>
        /// <returns></returns> 
        public ElasticClient GetClient()
        {
            if (_EsConfig == null || _EsConfig.Value == null || _EsConfig.Value.Urls == null || _EsConfig.Value.Urls.Count < 1)
            {
                throw new Exception("urls can not be null");
            }
            return GetClient(_EsConfig.Value.Urls.ToArray(), "");
        }
        /// <summary>
        /// 指定index获取ElasticClient
        /// </summary>
        /// <param name="indexName"></param>
        /// <returns></returns>
        public ElasticClient GetClient(string indexName)
        {
            if (_EsConfig == null || _EsConfig.Value == null || _EsConfig.Value.Urls == null || _EsConfig.Value.Urls.Count < 1)
            {
                throw new Exception("urls can not be null");
            }
            return GetClient(_EsConfig.Value.Urls.ToArray(), indexName);
        }


        /// <summary>
        /// 根据url获取ElasticClient
        /// </summary>
        /// <param name="url"></param>
        /// <param name="defaultIndex"></param>
        /// <returns></returns>
        private ElasticClient GetClient(string url, string defaultIndex = "")
        {
            if (string.IsNullOrWhiteSpace(url))
            {
                throw new Exception("es 地址不可为空");
            }
            var uri = new Uri(url);
            var connectionSetting = new ConnectionSettings(uri);
            if (!string.IsNullOrWhiteSpace(url))
            {
                connectionSetting.DefaultIndex(defaultIndex);
            }
            return new ElasticClient(connectionSetting);
        }
        /// <summary>
        /// 根据urls获取ElasticClient
        /// </summary>
        /// <param name="urls"></param>
        /// <param name="defaultIndex"></param>
        /// <returns></returns>
        private ElasticClient GetClient(string[] urls, string defaultIndex = "")
        {
            if (urls == null || urls.Length < 1)
            {
                throw new Exception("urls can not be null");
            }
            var uris = urls.Select(p => new Uri(p)).ToArray();
            var connectionPool = new SniffingConnectionPool(uris);
            var connectionSetting = new ConnectionSettings(connectionPool);
            if (!string.IsNullOrWhiteSpace(defaultIndex))
            {
                connectionSetting.DefaultIndex(defaultIndex);
            }
            //connectionSetting.BasicAuthentication("", ""); //设置账号密码

            return new ElasticClient(connectionSetting);
        }
    }
}

 

 

 6. 扩展 ElasticClient 类 ElasticClientExtension.cs

using Nest;

namespace NETCORE.TestElasticsearch.ESPackage
{
    /// <summary>
    /// ElasticClient 扩展类
    /// </summary>
    public static class ElasticClientExtension
    {
        /// <summary>
        /// 创建索引
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="elasticClient"></param>
        /// <param name="indexName"></param>
        /// <param name="numberOfShards"></param>
        /// <param name="numberOfReplicas"></param>
        /// <returns></returns>
        public static bool CreateIndex<T>(this ElasticClient elasticClient, string indexName = "", int numberOfShards = 5, int numberOfReplicas = 1) where T : class
        {

            if (string.IsNullOrWhiteSpace(indexName))
            {
                indexName = typeof(T).Name;
            }

            if (elasticClient.Indices.Exists(indexName).Exists)
            {
                return false;
            }
            else
            {
                var indexState = new IndexState()
                {
                    Settings = new IndexSettings()
                    {
                        NumberOfReplicas = numberOfReplicas,
                        NumberOfShards = numberOfShards,
                    },
                };
                var response = elasticClient.Indices.Create(indexName, p => p.InitializeUsing(indexState).Map<T>(p => p.AutoMap()));
                return response.Acknowledged;
            }
        }
    }
}

 

7. 创建ElasticSearch操作基类 BaseEsContext.cs

using Nest;

namespace NETCORE.TestElasticsearch.ESPackage
{
    /// <summary>
    /// 接口限定
    /// </summary>
    public interface IBaseEsContext { }
    /// <summary>
    /// es操作基类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class BaseEsContext<T> : IBaseEsContext where T : class
    {
        protected IEsClientProvider _EsClientProvider;
        public abstract string IndexName { get; }
        public BaseEsContext(IEsClientProvider provider)
        {
            _EsClientProvider = provider;
        }

        /// <summary>
        /// 批量更新
        /// </summary>
        /// <param name="tList"></param>
        /// <returns></returns>
        public bool InsertMany(List<T> tList)
        {
            var client = _EsClientProvider.GetClient(IndexName);
            if (!client.Indices.Exists(IndexName).Exists)
            {
                client.CreateIndex<T>(IndexName);
            }
            var response = client.IndexMany(tList);
            //var response = client.Bulk(p=>p.Index(IndexName).IndexMany(tList));
            return response.IsValid;
        }

        /// <summary>
        /// 获取总数
        /// </summary>
        /// <returns></returns>
        public long GetTotalCount()
        {
            var client = _EsClientProvider.GetClient(IndexName);
            var search = new SearchDescriptor<T>().MatchAll(); //指定查询字段 .Source(p => p.Includes(x => x.Field("Id")));
            var response = client.Search<T>(search);
            return response.Total;
        }
        /// <summary>
        /// 根据Id删除数据
        /// </summary>
        /// <returns></returns>
        public bool DeleteById(string id)
        {
            var client = _EsClientProvider.GetClient(IndexName);
            var response = client.Delete<T>(id);
            return response.IsValid;
        }

    }
}

 

 

8. 创建ElasticSearch具体操作类 AddressContext.cs

using Nest;

namespace NETCORE.TestElasticsearch.ESPackage
{

    /// <summary>
    /// 地址操作类
    /// </summary>
    public class AddressContext : BaseEsContext<Address>
    {
        /// <summary>
        /// 索引名称
        /// </summary>
        public override string IndexName => "address";
        public AddressContext(IEsClientProvider provider) : base(provider)
        {
        }
        /// <summary>
        /// 获取地址
        /// </summary>
        /// <param name="province"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public List<Address> GetAddresses(string province, int pageIndex, int pageSize)
        {
            var client = _EsClientProvider.GetClient(IndexName);
            var musts = new List<Func<QueryContainerDescriptor<Address>, QueryContainer>>();
            musts.Add(p => p.Term(m => m.Field(x=>x.Pronvince).Value(province)));
            var search = new SearchDescriptor<Address>();
           // search = search.Index(IndexName).Query(p => p.Bool(m => m.Must(musts))).From((pageIndex - 1) * pageSize).Take(pageSize);
            search =search.Query(p => p.Bool(m => m.Must(musts))).From((pageIndex - 1) * pageSize).Take(pageSize);
            var response = client.Search<Address>(search);
            return response.Documents.ToList();
        }
        /// <summary>
        /// 获取所有地址
        /// </summary>
        /// <returns></returns>
        public List<Address> GetAllAddresses()
        { 
            var client = _EsClientProvider.GetClient(IndexName);  
            var searchDescriptor = new SearchDescriptor<Address>();
            // searchDescriptor = searchDescriptor.Index(IndexName).Query(p => p.MatchAll());
            searchDescriptor = searchDescriptor.Query(p => p.MatchAll());
            var response = client.Search<Address>(searchDescriptor);
            return response.Documents.ToList();
        } 
        /// <summary>
        /// 删除指定城市的数据
        /// </summary>
        /// <param name="city"></param>
        /// <returns></returns>
        public bool DeleteByQuery(string city)
        {
            var client = _EsClientProvider.GetClient(IndexName);
            var musts = new  List<Func<QueryContainerDescriptor<Address>, QueryContainer>>();
            musts.Add(p=>p.Term(m=>m.Field(f=>f.City).Value(city)));
            var search = new DeleteByQueryDescriptor<Address>().Index(IndexName);
            search = search.Query(p => p.Bool(m => m.Must(musts)));
            var response = client.DeleteByQuery<Address>(p=>search);
            return response.IsValid;
        }

    }
}

 

 

 9. 创建 address 实体类 Address.cs

using Nest;

namespace NETCORE.TestElasticsearch.ESPackage
{
    [ElasticsearchType(IdProperty = "Id")]
    public class Address
    {
        [Keyword]
        public string Id { get; set; }
        [Keyword]
        public string Country { get; set; }
        [Keyword]
        public string City { get; set; }
        [Keyword]
        public string Pronvince { get; set; }
        [Keyword]
        public string Area { get; set; }
        [Text]
        public string Address1 { get; set; }

    }
}

 

 

 10. 项目中注入和使用ElasticSearch , Program.cs

using NETCORE.TestElasticsearch;
using NETCORE.TestElasticsearch.ESPackage;
using System.Reflection;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers(); 
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

builder.Services.Configure<EsConfig>(options =>
       {
           options.Urls = builder.Configuration.GetSection("EsConfig:ConnectionStrings").GetChildren().ToList().Select(p => p.Value).ToList();
       });

builder.Services.AddSingleton<IEsClientProvider, EsClientProvider>();
builder.Services.AddTransient<AddressContext, AddressContext>();

var app = builder.Build();
 
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

 

 

 11. 调用测试,创建 控制器 AddressController.cs

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using NETCORE.TestElasticsearch.ESPackage;

namespace NETCORE.TestElasticsearch.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class AddressController : ControllerBase
    {
        private AddressContext _AddressContext;
        public AddressController(AddressContext context)
        {
            _AddressContext = context;
        }
        /// <summary>
        /// 新增或者修改
        /// </summary>
        /// <param name="address"></param>
        [HttpPost("addAddress")]
        public void AddAddress(List<Address> addressList)
        {
            if (addressList == null || addressList.Count < 1)
            {
                return;
            }
            _AddressContext.InsertMany(addressList);
        }

        /// <summary>
        /// 删除地址
        /// </summary>
        /// <param name="id"></param>
        [HttpPost("deleteAddress")]
        public void DeleteAdress(string id)
        {
            _AddressContext.DeleteById(id);
        }
        /// <summary>
        /// 获取所有与地址
        /// </summary>
        /// <returns></returns>
        [HttpGet("getAllAddress")]
        public List<Address> GetAllAddress()
        {
            return _AddressContext.GetAllAddresses();
        }
        /// <summary>
        /// 获取地址总数
        /// </summary>
        /// <returns></returns>
        [HttpGet("getAddressTotalCount")]
        public long GetAddressTotalCount()
        {
            return _AddressContext.GetTotalCount();
        }

        /// <summary>
        /// 分页获取(可以进一步封装查询条件)
        /// </summary>
        /// <param name="province"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        [HttpPost("getAddressByProvince")]
        public List<Address> GetAddressByProvince(string province, int pageIndex, int pageSize)
        {
            return _AddressContext.GetAddresses(province, pageIndex, pageSize);
        }
    }
}

 

 

 启动后,打开 swagger 页面,调用 addAddress 接口,增加数据

[
  {
    "id": "1",
    "country": "标圡",
    "city": "天津",
    "pronvince": "中轲保",
    "area": "肿灯",
    "address1": "具全的地址"
  }
]

 

 调用成功。

调用 getAllAddress 接口,可查询到结果数据。

 

 

 

打开 Elasticsearch-head,可查看到。 地址:http://localhost:9100/ 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

引用:https://blog.csdn.net/xwnxwn/article/details/113825969

 

posted @ 2022-10-08 17:01  无心々菜  阅读(373)  评论(0编辑  收藏  举报