123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- using Elasticsearch.Net;
- using JiaZhiQuan.Common.ElasticSearch.Models;
- using JiaZhiQuan.Common.Utils;
- using Newtonsoft.Json;
- using Newtonsoft.Json.Linq;
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Diagnostics;
- using System.Linq;
- using System.Reflection;
- using System.Text;
- using System.Threading.Tasks;
- using Wicture.DbRESTFul;
- using Wicture.DbRESTFul.Configuration;
- namespace JiaZhiQuan.Common.ElasticSearch
- {
- public class ESHelper
- {
- #region models
- public class PaginationResult<T>
- {
- public List<T> Items { get; set; }
- public PaginationModel Pagination { get; set; }
- }
- public class PaginationModel
- {
- public int TotalCount { get; set; }
- public int PageIndex { get; set; }
- public int PageSize { get; set; }
- }
- #endregion
- private static object syncObj = new object();
- private static ElasticLowLevelClient _client = null;
- public static ElasticLowLevelClient Client
- {
- get
- {
- if (_client == null)
- {
- lock (syncObj)
- {
- if (_client == null)
- {
- var config = ConfigurationManager.Settings.GetConfig<ElasticSearchConfig>(ElasticSearchConfig.ConfigSectionName);
- var settings = new ConnectionConfiguration(new Uri(config.Url))
- .BasicAuthentication(config.User, config.Password)
- .RequestTimeout(TimeSpan.FromMinutes(1));
- _client = new ElasticLowLevelClient(settings);
- }
- }
- }
- return _client;
- }
- }
- /// <summary>
- /// pageSize > 0时,页码才起作用
- /// </summary>
- /// <returns></returns>
- public async static Task<PaginationResult<T>> Query<T>(string index, object postData, int pageIndex = 0, int pageSize = 0)
- {
- SearchRequestParameters parameters = new SearchRequestParameters();
- if (pageSize > 0)
- {
- parameters.SetQueryString("size", pageSize);
- if (pageIndex > 0)
- {
- parameters.SetQueryString("from", (pageIndex - 1) * pageSize);
- }
- }
- try
- {
- var resp = await Client.SearchAsync<StringResponse>(index, PostData.Serializable(postData), parameters);
- if (resp.Success)
- {
- var obj = JsonConvert.DeserializeObject<JToken>(resp.Body);
- var j = new List<dynamic>();
- var totalCount = obj.Value<JObject>("hits")?.Value<JToken>("total")?.Value<int>("value") ?? 0;
- var hits = obj.Value<JObject>("hits")?.Value<JArray>("hits")?.Select(e => JsonConvert.DeserializeObject<T>(e.Value<JToken>("_source").ToString()))?.ToList();
- return new PaginationResult<T>
- {
- Items = hits,
- Pagination = new PaginationModel
- {
- PageIndex = pageIndex,
- PageSize = pageSize,
- TotalCount = totalCount
- }
- };
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.Message);
- throw ex;
- }
- return null;
- }
- public async static Task<JToken> Get(string index, string id, GetRequestParameters param = null)
- {
- var resp = await Client.GetAsync<StringResponse>(index, id, param);
- if (resp.Success)
- {
- var obj = JsonConvert.DeserializeObject<JToken>(resp.Body);
- return obj.Value<JToken>("_source");
- }
- return null;
- }
- public async static Task<bool> CheckExist(string index, string id)
- {
- var resp = await Client.DocumentExistsAsync<StringResponse>(index, id);
- return resp.Success;
- }
- /// <summary>
- /// 解析ES返回的对象,提取数据和数据条数
- /// </summary>
- /// <typeparam name="T">需要序列化成的对象,属性名需要和ES的字段名一样,如果不一样需要设置特性</typeparam>
- /// <param name="response">ES返回的对象</param>
- /// <param name="methodName">调用本方法的方法名称,用来记录异常日志,如果解析失败可以通过名称定位到具体是哪个方法调用的</param>
- /// <returns></returns>
- public static ESResponseData<T> GetResponseData<T>(StringResponse response)
- {
- ESResponseData<T> res = new ESResponseData<T>();
- if (response is null)
- {
- res.errorMsg = "response is null";
- return res;
- }
- var stacktrace = new StackTrace();
- var method = stacktrace.GetFrame(1).GetMethod();
- string methodName = stacktrace.GetFrame(1).GetMethod().DeclaringType.FullName;
- if (response.Success)
- {
- try
- {
- var jsonData = JsonConvert.DeserializeObject<JToken>(response.Body);
- res.total = jsonData.Value<JObject>(ESConstants.ResponseKey.HITS)
- ?.Value<JObject>(ESConstants.ResponseKey.HITS_TOTAL)
- ?.Value<int?>(ESConstants.ResponseKey.HITS_TOTAL_VALUE)
- ?? 0;
- PropertyInfo[] properties = typeof(T).GetProperties();
- res.data = jsonData.Value<JObject>(ESConstants.ResponseKey.HITS)
- ?.Value<JArray>(ESConstants.ResponseKey.HITS_HITS)
- ?.Select(e =>
- {
- var source = e.Value<JToken>(ESConstants.ResponseKey.HITS_HITS_SOURCE);
- T itemData = Activator.CreateInstance<T>();
- foreach (PropertyInfo property in properties)
- {
- object newValue = null;
- ESIdAttribute idAttribute = property.GetCustomAttribute<ESIdAttribute>();
- if (idAttribute != null)
- {
- // 主键
- newValue = e.Value<JToken>(ESConstants.ResponseKey.HITS_HITS_ID).Value<string>();
- }
- else
- {
- // 业务字段
- ESFieldAttribute attribute = property.GetCustomAttribute<ESFieldAttribute>();
- // 如果没有设置特性,或者特性没有设置映射的名称,那么就用属性名作为ES的字段名查询数据
- if (attribute is null || string.IsNullOrWhiteSpace(attribute.ESFieldName))
- {
- var value = (source[property.Name] as JValue)?.Value;
- newValue = ObjectUtils.ConvertObjectToType(value, property.PropertyType);
- }
- // 如果设置了特性,而且ESFieldName不为空,那么就用ESFieldName作为ES的字段名查询数据
- else if (attribute != null && !string.IsNullOrWhiteSpace(attribute.ESFieldName))
- {
- var value = (source[attribute.ESFieldName] as JValue)?.Value;
- newValue = ObjectUtils.ConvertObjectToType(value, property.PropertyType);
- }
- }
- property.SetValue(itemData, newValue, null);
- }
- return itemData;
- })
- ?.ToList();
- res.success = true;
- }
- catch (Exception ex)
- {
- res.errorMsg = ex.Message;
- LoggerManager.Logger.Error($"【{methodName}】ES解析数据报错: {ex}");
- }
- }
- else
- {
- res.errorMsg = response.OriginalException.ToString();
- LoggerManager.Logger.Error($"【{methodName}】ES解析数据失败: {response?.ToString()}");
- }
- return res;
- }
- /// <summary>
- /// 解析ES返回的对象,提取统计结果
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="response"></param>
- /// <returns></returns>
- public static ESResponseAggregations GetResponseAggregations(StringResponse response)
- {
- ESResponseAggregations res = new ESResponseAggregations();
- if (response is null)
- {
- res.errorMsg = "response is null";
- return res;
- }
- var stacktrace = new StackTrace();
- var method = stacktrace.GetFrame(1).GetMethod();
- string methodName = stacktrace.GetFrame(1).GetMethod().DeclaringType.FullName;
- if (response.Success)
- {
- try
- {
- var dic = new Dictionary<string, int>();
- var jsonData = JsonConvert.DeserializeObject<JToken>(response.Body);
- var aggs = jsonData.Value<JObject>(ESConstants.ResponseKey.AGGREGATIONS);
- foreach (var item in aggs)
- {
- dic.Add(item.Key, item.Value.Value<int>(ESConstants.ResponseKey.AGGREGATIONS_COUNT));
- }
- res.data = dic;
- res.success = true;
- }
- catch (Exception ex)
- {
- res.errorMsg = ex.Message;
- LoggerManager.Logger.Error($"【{methodName}】ES解析数据报错: {ex}");
- }
- }
- else
- {
- res.errorMsg = response.OriginalException.ToString();
- LoggerManager.Logger.Error($"【{methodName}】ES解析聚合结果失败: {response?.ToString()}");
- }
- return res;
- }
- }
- }
|