隐藏

C#基础知识点搜索引擎ElasticSearch的使用

发布:2023/1/16 14:29:22作者:管理员 来源:本站 浏览次数:330

项目需要添加Elasticsearch.Net和Nest


相关文档地址


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

1、封装ElasticClient提供者


1)创建ElasticSearch配置类


public class EsConfig : IOptions<EsConfig>

   {<!-- -->

       public List<string> Urls {<!-- --> get; set; }


       public EsConfig Value => this;

   }


2)创建ElasticSearch提供者接口以及类


/// <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);

   }




   /// <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);

           }

           return new ElasticClient(connectionSetting);

       }

   }


---------用户密码验证(注释部分),可以配置在EsConfig中---------


/// <summary>

       /// 根据urls获取ElasticClient

       /// </summary>

       /// <param name="urls"></param>

       /// <param name="defaultIndex"></param>

       /// <returns></returns>

       public 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);

       }


2、封装操作ElasticSearch实现


1)、扩展ElasticClient类


/// <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;

           }

       }

   }


2)、创建ElasticSearch操作基类


/// <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;

       }


   }


3)、具体操作类(示例)


/// <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;

       }


   }


address类


[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; }


   }


3、项目中注入和使用ElasticSearch


1)、配置文件


1   "EsConfig": {<!-- -->

2     "ConnectionStrings": [ "http://127.0.0.1:9200/" ]

3   }


2)、注入ElasticSearch


services.Configure<EsConfig>(options =>

         {<!-- -->

             options.Urls = Configuration.GetSection("EsConfig:ConnectionStrings").GetChildren().ToList().Select(p => p.Value).ToList();


         });



           services.AddSingleton<IEsClientProvider, EsClientProvider>();

           var types = Assembly.Load("John.DotNetCoreStudy.EsCommon").GetTypes().Where(p => !p.IsAbstract && (p.GetInterfaces().Any(i => i == typeof(IBaseEsContext)))).ToList();

           types.ForEach(p =>

                   services.AddTransient(p)

               );


3)、Controller类中使用


[Route("api/[controller]")]

   [ApiController]

   public class AddressController : ControllerBase

   {<!-- -->

       private AddressContext _AddressContext;

       public AddressController(AddressContext context)

       {<!-- -->

           _AddressContext = context;

       }

       /// <summary>

       /// 新增或者修改

       /// </summary>

       /// <param name="address"></param>

       [HttpPost("添加地址")]

       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);

       }


   }


4、测试(略)


当然es还有很多操作的,聚合查询、不同条件的查询(范围查询、匹配查询等等)、分词等。具体可以去查看其官方文档对应实现!