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 { public List 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.ConfigSectionName); var settings = new ConnectionConfiguration(new Uri(config.Url)) .BasicAuthentication(config.User, config.Password) .RequestTimeout(TimeSpan.FromMinutes(1)); _client = new ElasticLowLevelClient(settings); } } } return _client; } } /// /// pageSize > 0时,页码才起作用 /// /// public async static Task> Query(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(index, PostData.Serializable(postData), parameters); if (resp.Success) { var obj = JsonConvert.DeserializeObject(resp.Body); var j = new List(); var totalCount = obj.Value("hits")?.Value("total")?.Value("value") ?? 0; var hits = obj.Value("hits")?.Value("hits")?.Select(e => JsonConvert.DeserializeObject(e.Value("_source").ToString()))?.ToList(); return new PaginationResult { 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 Get(string index, string id, GetRequestParameters param = null) { var resp = await Client.GetAsync(index, id, param); if (resp.Success) { var obj = JsonConvert.DeserializeObject(resp.Body); return obj.Value("_source"); } return null; } public async static Task CheckExist(string index, string id) { var resp = await Client.DocumentExistsAsync(index, id); return resp.Success; } /// /// 解析ES返回的对象,提取数据和数据条数 /// /// 需要序列化成的对象,属性名需要和ES的字段名一样,如果不一样需要设置特性 /// ES返回的对象 /// 调用本方法的方法名称,用来记录异常日志,如果解析失败可以通过名称定位到具体是哪个方法调用的 /// public static ESResponseData GetResponseData(StringResponse response) { ESResponseData res = new ESResponseData(); 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(response.Body); res.total = jsonData.Value(ESConstants.ResponseKey.HITS) ?.Value(ESConstants.ResponseKey.HITS_TOTAL) ?.Value(ESConstants.ResponseKey.HITS_TOTAL_VALUE) ?? 0; PropertyInfo[] properties = typeof(T).GetProperties(); res.data = jsonData.Value(ESConstants.ResponseKey.HITS) ?.Value(ESConstants.ResponseKey.HITS_HITS) ?.Select(e => { var source = e.Value(ESConstants.ResponseKey.HITS_HITS_SOURCE); T itemData = Activator.CreateInstance(); foreach (PropertyInfo property in properties) { object newValue = null; ESIdAttribute idAttribute = property.GetCustomAttribute(); if (idAttribute != null) { // 主键 newValue = e.Value(ESConstants.ResponseKey.HITS_HITS_ID).Value(); } else { // 业务字段 ESFieldAttribute attribute = property.GetCustomAttribute(); // 如果没有设置特性,或者特性没有设置映射的名称,那么就用属性名作为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; } /// /// 解析ES返回的对象,提取统计结果 /// /// /// /// 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(); var jsonData = JsonConvert.DeserializeObject(response.Body); var aggs = jsonData.Value(ESConstants.ResponseKey.AGGREGATIONS); foreach (var item in aggs) { dic.Add(item.Key, item.Value.Value(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; } } }