针对 ElasticSearch .Net 客户端的一些封装

ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

  ElasticSearch 为.net提供了两个客户端,分别是 Elasticsearch.Net  和  NEST 

  Elasticsearch.net为什么会有两个客户端?

  Elasticsearch.Net是一个非常底层且灵活的客户端,它不在意你如何的构建自己的请求和响应。它非常抽象,因此所有的Elasticsearch API被表示为方法,没有太多关于你想如何构建json/request/response对象的东东,并且它还内置了可配置、可重写的集群故障转移机制。

  Elasticsearch.Net有非常大的弹性,如果你想更好的提升你的搜索服务,你完全可以使用它来做为你的客户端。

  NEST是一个高层的客户端,可以映射所有请求和响应对象,拥有一个强类型查询DSL(领域特定语言),并且可以使用.net的特性比如协变、Auto Mapping Of POCOs,NEST内部使用的依然是Elasticsearch.Net客户端。

  具体客户端的用法可参考官方的文档说明,本文主要针对 NEST 的查询做扩展。

  起因:之前在学习Dapper的时候看过一个 DapperExtensions 的封装 其实Es的查询基本就是类似Sql的查询 。因此参考DapperExtensions 进行了Es版本的迁移

  通过官网说明可以看到  NEST  的对象初始化的方式进行查询  都是已下面的方式开头:

var searchRequest = new SearchRequest<XXT>(XXIndex)

  我们可以通过查看源码

   我们可以看到所有的查询基本都是在SearchRequest上面做的扩展  这样我们也可以开始我们的第一步操作:

  1.关于分页,我们定义如下分页对象:  

 1 /// <summary>
 2     /// 分页类型
 3     /// </summary>
 4     public class PageEntity
 5     {
 6         /// <summary>
 7         ///     每页行数
 8         /// </summary>
 9         public int PageSize { get; set; }
10
11         /// <summary>
12         ///     当前页
13         /// </summary>
14         public int PageIndex { get; set; }
15
16         /// <summary>
17         ///     总记录数
18         /// </summary>
19         public int Records { get; set; }
20
21         /// <summary>
22         ///     总页数
23         /// </summary>
24         public int Total
25         {
26             get
27             {
28                 if (Records > 0)
29                     return Records % PageSize == 0 ? Records / PageSize : Records / PageSize + 1;
30
31                 return 0;
32             }
33         }
34
35
36         /// <summary>
37         ///     排序列
38         /// </summary>
39         public string Sidx { get; set; }
40
41         /// <summary>
42         ///     排序类型
43         /// </summary>
44         public string Sord { get; set; }
45     }

  2.定义ElasticsearchPage 分页对象

/// <summary>
    ///     ElasticsearchPage
    /// </summary>
    public class ElasticsearchPage<T> : PageEntity
    {
        public string Index { get; set; }

        public ElasticsearchPage(string index)
        {
            Index = index;
        }

        /// <summary>
        /// InitSearchRequest
        /// </summary>
        /// <returns></returns>
        public SearchRequest<T> InitSearchRequest()
        {
            return new SearchRequest<T>(Index)
            {
                From = (PageIndex - 1) * PageSize,
                Size = PageSize
            };
        }
    }

  至此我们的SearchRequest的初始化操作已经完成了我们可以通过如下方式进行调用

1  var elasticsearchPage = new ElasticsearchPage<Content>("content")
2             {
3                 PageIndex = pageIndex,
4                 PageSize = pageSize
5             };
6
7 var searchRequest = elasticsearchPage.InitSearchRequest();

通过SearchRequest的源码我们可以得知,所有的查询都是基于内部属性进行(扩展的思路来自DapperExtensions):

   3.QueryContainer的扩展 ,类似Where 语句:

  我们定义一个 比较操作符 类似 Sql中的  like  !=  in  等等

 1 /// <summary>
 2     ///     比较操作符
 3     /// </summary>
 4     public enum ExpressOperator
 5     {
 6         /// <summary>
 7         ///     精准匹配 term(主要用于精确匹配哪些值,比如数字,日期,布尔值或 not_analyzed 的字符串(未经分析的文本数据类型): )
 8         /// </summary>
 9         Eq,
10
11         /// <summary>
12         ///     大于
13         /// </summary>
14         Gt,
15
16         /// <summary>
17         ///     大于等于
18         /// </summary>
19         Ge,
20
21         /// <summary>
22         ///     小于
23         /// </summary>
24         Lt,
25
26         /// <summary>
27         ///     小于等于
28         /// </summary>
29         Le,
30
31         /// <summary>
32         ///     模糊查询 (You can use % in the value to do wilcard searching)
33         /// </summary>
34         Like,
35
36         /// <summary>
37         /// in 查询
38         /// </summary>
39         In
40     }

  接着我们定义一个 如下接口,主要包括:

  1. 提供返回一个 QueryContainer GetQuery方法

  2. 属性名称 PropertyName

  3. 操作符 ExpressOperator

  4. 谓词值 Value

 1  /// <summary>
 2     ///     谓词接口
 3     /// </summary>
 4     public interface IPredicate
 5     {
 6         QueryContainer GetQuery(QueryContainer query);
 7     }
 8
 9     /// <summary>
10     ///     基础谓词接口
11     /// </summary>
12     public interface IBasePredicate : IPredicate
13     {
14         /// <summary>
15         ///     属性名称
16         /// </summary>
17         string PropertyName { get; set; }
18     }
19
20     public abstract class BasePredicate : IBasePredicate
21     {
22         public string PropertyName { get; set; }
23         public abstract QueryContainer GetQuery(QueryContainer query);
24     }
25
26     /// <summary>
27     ///     比较谓词
28     /// </summary>
29     public interface IComparePredicate : IBasePredicate
30     {
31         /// <summary>
32         ///     操作符
33         /// </summary>
34         ExpressOperator ExpressOperator { get; set; }
35     }
36
37     public abstract class ComparePredicate : BasePredicate
38     {
39         public ExpressOperator ExpressOperator { get; set; }
40     }
41
42     /// <summary>
43     ///     字段谓词
44     /// </summary>
45     public interface IFieldPredicate : IComparePredicate
46     {
47         /// <summary>
48         ///     谓词的值
49         /// </summary>
50         object Value { get; set; }
51     }

  具体实现定义 FieldPredicate  并且继承如上接口,通过操作符映射为 Nest具体查询对象

 1 public class FieldPredicate<T> : ComparePredicate, IFieldPredicate
 2         where T : class
 3     {
 4         public object Value { get; set; }
 5
 6         public override QueryContainer GetQuery(QueryContainer query)
 7         {
 8             switch (ExpressOperator)
 9             {
10                 case ExpressOperator.Eq:
11                     query = new TermQuery
12                     {
13                         Field = PropertyName,
14                         Value = Value
15                     };
16                     break;
17                 case ExpressOperator.Gt:
18                     query = new TermRangeQuery
19                     {
20                         Field = PropertyName,
21                         GreaterThan = Value.ToString()
22                     };
23                     break;
24                 case ExpressOperator.Ge:
25                     query = new TermRangeQuery
26                     {
27                         Field = PropertyName,
28                         GreaterThanOrEqualTo = Value.ToString()
29                     };
30                     break;
31                 case ExpressOperator.Lt:
32                     query = new TermRangeQuery
33                     {
34                         Field = PropertyName,
35                         LessThan = Value.ToString()
36                     };
37                     break;
38                 case ExpressOperator.Le:
39                     query = new TermRangeQuery
40                     {
41                         Field = PropertyName,
42                         LessThanOrEqualTo = Value.ToString()
43                     };
44                     break;
45                 case ExpressOperator.Like:
46                     query = new MatchPhraseQuery
47                     {
48                         Field = PropertyName,
49                         Query = Value.ToString()
50                     };
51                     break;
52                 case ExpressOperator.In:
53                     query = new TermsQuery
54                     {
55                         Field = PropertyName,
56                         Terms=(List<object>)Value
57                     };
58                     break;
59                 default:
60                     throw new ElasticsearchException("构建Elasticsearch查询谓词异常");
61             }
62             return query;
63         }
64     }

  4.定义好这些后我们就可以拼接我们的条件了,我们定义了 PropertyName  但是我们更倾向于一种类似EF的查询方式  可以通过 Expression<Func<T, object>> 的方式所以我们这边提供一个泛型方式

,因为在创建 Elasticsearch  文档的时候我们已经建立了Map 文件 我们通过反射读取 PropertySearchName属性  就可以读取到我们的 PropertyName  这边 PropertySearchName 是自己定义的属性

为什么不反解Nest 的属性   针对不同类型需要反解的属性也是不相同的  所以避免麻烦 直接重新定义了新的属性 。代码如下:

1 public class PropertySearchNameAttribute: Attribute
2     {
3         public PropertySearchNameAttribute(string name)
4         {
5             Name = name;
6         }
7         public string Name { get; set; }
8     }

然后我们就可以来定义的们初始化IFieldPredicate 的方法了

 首先我们解析我们的需求:

  1.我们需要一个Expression<Func<T, object>>

  2.我们需要一个操作符

  3.我们需要比较什么值

针对需求我们可以得到这样一个方法:

注:所依赖的反射方法详解文末

 1 /// <summary>
 2         ///     工厂方法创建一个新的  IFieldPredicate 谓语: [FieldName] [Operator] [Value].
 3         /// </summary>
 4         /// <typeparam name="T">实例类型</typeparam>
 5         /// <param name="expression">返回左操作数的表达式  [FieldName].</param>
 6         /// <param name="op">比较运算符</param>
 7         /// <param name="value">谓语的值.</param>
 8         /// <returns>An instance of IFieldPredicate.</returns>
 9         public static IFieldPredicate Field<T>(Expression<Func<T, object>> expression, ExpressOperator op, object value) where T : class
10         {
11             var propertySearchName = (PropertySearchNameAttribute)
12                 LoadAttributeHelper.LoadAttributeByType<T, PropertySearchNameAttribute>(expression);
13
14             return new FieldPredicate<T>
15             {
16                 PropertyName = propertySearchName.Name,
17                 ExpressOperator = op,
18                 Value = value
19             };
20         }

然后 我们就可以像之前拼接sql的方式来进行拼接条件了

就以我们项目中的业务需求做个演示

1  var predicateList = new List<IPredicate>();
2 //最大价格
3 if (requestContentDto.MaxPrice != null)
4                 predicateList.Add(Predicates.Field<Content>(x => x.UnitPrice, ExpressOperator.Le,
5                     requestContentDto.MaxPrice));
6 //最小价格
7 if (requestContentDto.MinPrice != null)
8                 predicateList.Add(Predicates.Field<Content>(x => x.UnitPrice, ExpressOperator.Ge,
9                     requestContentDto.MinPrice));

然后针对实际业务我们在写sql的时候就回有  (xx1  and  xx2) or  xx3 这样的业务需求了

针对这种业务需求  我们需要在提供一个 IPredicateGroup 进行分组查询谓词

首先我们定义一个PredicateGroup 加入谓词时使用的操作符 GroupOperator

1     /// <summary>
2     ///     PredicateGroup 加入谓词时使用的操作符
3     /// </summary>
4     public enum GroupOperator
5     {
6         And,
7         Or
8     }

然后我们定义 IPredicateGroup 及实现

 1  /// <summary>
 2     ///     分组查询谓词
 3     /// </summary>
 4     public interface IPredicateGroup : IPredicate
 5     {
 6         /// <summary>
 7         /// </summary>
 8         GroupOperator Operator { get; set; }
 9
10         IList<IPredicate> Predicates { get; set; }
11     }
12
13     /// <summary>
14     ///     分组查询谓词
15     /// </summary>
16     public class PredicateGroup : IPredicateGroup
17     {
18         public GroupOperator Operator { get; set; }
19         public IList<IPredicate> Predicates { get; set; }
20
21         /// <summary>
22         ///     GetQuery
23         /// </summary>
24         /// <param name="query"></param>
25         /// <returns></returns>
26         public QueryContainer GetQuery(QueryContainer query)
27         {
28             switch (Operator)
29             {
30                 case GroupOperator.And:
31                     return Predicates.Aggregate(query, (q, p) => q && p.GetQuery(query));
32                 case GroupOperator.Or:
33                     return Predicates.Aggregate(query, (q, p) => q || p.GetQuery(query));
34                 default:
35                     throw new ElasticsearchException("构建Elasticsearch查询谓词异常");
36             }
37         }
38     }

现在我们可以用 PredicateGroup来组装我们的 谓词

 同样解析我们的需求:

  1.我们需要一个GroupOperator

  2.我们需要谓词列表 IPredicate[]

针对需求我们可以得到这样一个方法:

 1  /// <summary>
 2         ///     工厂方法创建一个新的 IPredicateGroup 谓语.
 3         ///     谓词组与其他谓词可以连接在一起.
 4         /// </summary>
 5         /// <param name="op">分组操作时使用的连接谓词 (AND / OR).</param>
 6         /// <param name="predicate">一组谓词列表.</param>
 7         /// <returns>An instance of IPredicateGroup.</returns>
 8         public static IPredicateGroup Group(GroupOperator op, params IPredicate[] predicate)
 9         {
10             return new PredicateGroup
11             {
12                 Operator = op,
13                 Predicates = predicate
14             };
15         }

这样我们就可以进行组装了

用法:

 1 //构建或查询
 2
 3 var predicateList= new List<IPredicate>();
 4
 5 //关键词
 6 if (!string.IsNullOrWhiteSpace(requestContentDto.SearchKey))
 7 predicateList.Add(Predicates.Field<Content>(x => x.Title, ExpressOperator.Like,
 8 requestContentDto.SearchKey));
 9
10 var predicate = Predicates.Group(GroupOperator.And, predicateList.ToArray());
11 //构建或查询
12 var predicateListOr = new List<IPredicate>();
13 if (!string.IsNullOrWhiteSpace(requestContentDto.Brand))
14 {
15 var array = requestContentDto.Brand.Split(‘,‘).ToList();
16 predicateListOr
17 .AddRange(array.Select
18 (item => Predicates.Field<Content>(x => x.Brand, ExpressOperator.Like, item)));
19 }
20
21 var predicateOr = Predicates.Group(GroupOperator.Or, predicateListOr.ToArray());
22
23 var predicatecCombination = new List<IPredicate> {predicate, predicateOr};
24 var pgCombination = Predicates.Group(GroupOperator.And, predicatecCombination.ToArray());

然后我们的  IPredicateGroup  优雅的和  ISearchRequest 使用呢  我们提供一个链式的操作方法

 1  /// <summary>
 2         /// 初始化query
 3         /// </summary>
 4         /// <param name="searchRequest"></param>
 5         /// <param name="predicate"></param>
 6         public static ISearchRequest InitQueryContainer(this ISearchRequest searchRequest, IPredicate predicate)
 7         {
 8             if (predicate != null)
 9             {
10                 searchRequest.Query = predicate.GetQuery(searchRequest.Query);
11             }
12             return searchRequest;
13
14         }

至此我们的基础查询方法已经封装完成

然后通过 Nest 的进行查询即可

var response = ElasticClient.Search<T>(searchRequest);

具体演示代码(以项目的业务)

  1  var elasticsearchPage = new ElasticsearchPage<Content>("content")
  2             {
  3                 PageIndex = pageIndex,
  4                 PageSize = pageSize
  5             };
  6
  7             #region terms 分组
  8
  9             var terms = new List<IFieldTerms>();
 10             var classificationGroupBy = "searchKey_classification";
 11             var brandGroupBy = "searchKey_brand";
 12
 13             #endregion
 14
 15             var searchRequest = elasticsearchPage.InitSearchRequest();
 16             var predicateList = new List<IPredicate>();
 17             //分类ID
 18             if (requestContentDto.CategoryId != null)
 19                 predicateList.Add(Predicates.Field<Content>(x => x.ClassificationCode, ExpressOperator.Like,
 20                     requestContentDto.CategoryId));
 21             else
 22                 terms.Add(Predicates.FieldTerms<Content>(x => x.ClassificationGroupBy, classificationGroupBy, 200));
 23
 24             //品牌
 25             if (string.IsNullOrWhiteSpace(requestContentDto.Brand))
 26                 terms.Add(Predicates.FieldTerms<Content>(x => x.BrandGroupBy, brandGroupBy, 200));
 27             //供应商名称
 28             if (!string.IsNullOrWhiteSpace(requestContentDto.BaseType))
 29                 predicateList.Add(Predicates.Field<Content>(x => x.BaseType, ExpressOperator.Like,
 30                     requestContentDto.BaseType));
 31             //是否自营
 32             if (requestContentDto.IsSelfSupport == 1)
 33                 predicateList.Add(Predicates.Field<Content>(x => x.IsSelfSupport, ExpressOperator.Eq,
 34                     requestContentDto.IsSelfSupport));
 35             //最大价格
 36             if (requestContentDto.MaxPrice != null)
 37                 predicateList.Add(Predicates.Field<Content>(x => x.UnitPrice, ExpressOperator.Le,
 38                     requestContentDto.MaxPrice));
 39             //最小价格
 40             if (requestContentDto.MinPrice != null)
 41                 predicateList.Add(Predicates.Field<Content>(x => x.UnitPrice, ExpressOperator.Ge,
 42                     requestContentDto.MinPrice));
 43             //关键词
 44             if (!string.IsNullOrWhiteSpace(requestContentDto.SearchKey))
 45                 predicateList.Add(Predicates.Field<Content>(x => x.Title, ExpressOperator.Like,
 46                     requestContentDto.SearchKey));
 47
 48             //规整排序
 49             var sortConfig = SortOrderRule(requestContentDto.SortKey);
 50             var sorts = new List<ISort>
 51             {
 52                 Predicates.Sort<Content>(sortConfig.Key, sortConfig.SortOrder)
 53             };
 54
 55             var predicate = Predicates.Group(GroupOperator.And, predicateList.ToArray());
 56             //构建或查询
 57             var predicateListOr = new List<IPredicate>();
 58             if (!string.IsNullOrWhiteSpace(requestContentDto.Brand))
 59             {
 60                 var array = requestContentDto.Brand.Split(‘,‘).ToList();
 61                 predicateListOr
 62                     .AddRange(array.Select
 63                         (item => Predicates.Field<Content>(x => x.Brand, ExpressOperator.Like, item)));
 64             }
 65
 66             var predicateOr = Predicates.Group(GroupOperator.Or, predicateListOr.ToArray());
 67
 68             var predicatecCombination = new List<IPredicate> {predicate, predicateOr};
 69             var pgCombination = Predicates.Group(GroupOperator.And, predicatecCombination.ToArray());
 70
 71             searchRequest.InitQueryContainer(pgCombination)
 72                 .InitSort(sorts)
 73                 .InitHighlight(requestContentDto.HighlightConfigEntity)
 74                 .InitGroupBy(terms);
 75
 76             var data = _searchProvider.SearchPage(searchRequest);
 77
 78             #region terms 分组赋值
 79
 80             var classificationResponses = requestContentDto.CategoryId != null
 81                 ? null
 82                 : data.Aggregations.Terms(classificationGroupBy).Buckets
 83                     .Select(x => new ClassificationResponse
 84                     {
 85                         Key = x.Key.ToString(),
 86                         DocCount = x.DocCount
 87                     }).ToList();
 88
 89             var brandResponses = !string.IsNullOrWhiteSpace(requestContentDto.Brand)
 90                 ? null
 91                 : data.Aggregations.Terms(brandGroupBy).Buckets
 92                     .Select(x => new BrandResponse
 93                     {
 94                         Key = x.Key.ToString(),
 95                         DocCount = x.DocCount
 96                     }).ToList();
 97
 98             #endregion
 99
100             //初始化
101
102             #region 高亮
103
104             var titlePropertySearchName = (PropertySearchNameAttribute)
105                 LoadAttributeHelper.LoadAttributeByType<Content, PropertySearchNameAttribute>(x => x.Title);
106
107             var list = data.Hits.Select(c => new Content
108             {
109                 Key = c.Source.Key,
110                 Title = (string) c.Highlights.Highlight(c.Source.Title, titlePropertySearchName.Name),
111                 ImgUrl = c.Source.ImgUrl,
112                 BaseType = c.Source.BaseType,
113                 BelongMemberName = c.Source.BelongMemberName,
114                 Brand = c.Source.Brand,
115                 Code = c.Source.Code,
116                 BrandFirstLetters = c.Source.BrandFirstLetters,
117                 ClassificationName = c.Source.ClassificationName,
118                 ResourceStatus = c.Source.ResourceStatus,
119                 BrandGroupBy = c.Source.BrandGroupBy,
120                 ClassificationGroupBy = c.Source.ClassificationGroupBy,
121                 ClassificationCode = c.Source.ClassificationCode,
122                 IsSelfSupport = c.Source.IsSelfSupport,
123                 UnitPrice = c.Source.UnitPrice
124             }).ToList();
125
126             #endregion
127
128             var contentResponse = new ContentResponse
129             {
130                 Records = (int) data.Total,
131                 PageIndex = elasticsearchPage.PageIndex,
132                 PageSize = elasticsearchPage.PageSize,
133                 Contents = list,
134                 BrandResponses = brandResponses,
135                 ClassificationResponses = classificationResponses
136             };
137             return contentResponse;

关于排序、group by 、 高亮 的具体实现不做说明  思路基本一致  可以参考git上面的代码

源码详见 Git 

https://github.com/wulaiwei/WorkData.Core/tree/master/WorkData/WorkData.ElasticSearch

为什么要对 Nest 进行封装:

1.项目组不可能每个人都来熟悉一道 Nest的 api ,缩小上手难度

2.规范查询方式

  

原文地址:https://www.cnblogs.com/wulaiwei/p/9319821.html

时间: 2024-10-09 14:58:31

针对 ElasticSearch .Net 客户端的一些封装的相关文章

Elasticsearch RestHighLevelClient客户端封装

目录 EsClientRHL 开源源码地址 开发原因: 使用前你应该具有哪些技能 工具功能范围介绍 工具源码结构介绍 开始使用 未来规划 EsClientRHL EsClientRHL是一个可基于springboot的elasticsearch RestHighLevelClient客户端调用封装工具,主要提供了es索引结构工具.es索引数据增删改工具.es查询工具.es数据分析工具. 基于elasticsearch6.6+版本进行开发,由于采用RestHighLevelClient,所以版本兼

针对Elasticsearch的开源分析及可视化平台——Kibana

Kibana是一个针对Elasticsearch的开源分析及可视化平台,用来搜索.查看交互存储在Elasticsearch索引中的数据.使用Kibana,可以通过各种图表进行高级数据分析及展示. Kibana让海量数据更容易理解.它操作简单,基于浏览器的用户界面可以快速创建仪表板(dashboard)实时显示Elasticsearch查询动态. 在云市不需要复杂部署安装,一键使用Kibana.设置Kibana也非常简单,无需编码或者额外的基础架构,一分钟只能就能启动Elasticsearch索引

redis的java客户端Jedis简单封装

经过我们团队的一番讨论,最终决定使用redis来进行我们的业务缓存.redis会将数据缓存到内存中,运行效率会很快.同时异步将数据写入到磁盘中,进行持久化. 且redis支持主从同步,支持分布式部署,支持N多数据结构,这对于我们有着莫大的吸引力. 参见:http://blog.csdn.net/yichenlian/article/details/27207383 我们团队讨论的焦点是在于redis的灾备恢复问题.由于redis的持久化是异步的,总会有一点时间内存中数据和磁盘数据不同步的情况(当

web自动化针对PO模式进行二次封装之 basepage

在 PO 模式当中, 我们做到了 页面对象 与 测试用例 的 分离,但在页面对象编写时,我们仍然还有优化的空间.页面对象有一些共同的基本操作 ,可以封装起来,并可以在基本操作当中加上 日志 和 异常截图 的处理.比如说我们在查找元素时,都需要等待,在PO模式当中, 需要都写上 等待和查找元素,那么就可以将其封装起来,包括其它的一些比如:文本获取.元素属性获取.鼠标操作.窗口切换.iframe切换. alert弹框关闭. 文件上传.下拉框选择..... 当脚本运行的过程中,出现了用例失败,我们希望

ElasticSearch java客户端更新时出现的错误:NoNodeAvailableException[None of the configured nodes are available

下午尝试 用ElasticSearch  的java客户端去做数据检索工作,测试了一下批量更新,代码如下: public static void bulkUpdateGoods(List<Goods> goods) throws IOException, InterruptedException, ExecutionException { Client client = null; try { client = TransportClient.builder().build() .addTra

elasticsearch java 客户端之action简介

上一篇介绍了elasticsearch的client结构,client只是一个门面,在每个方法后面都有一个action来承接相应的功能.但是action也并非是真正的功能实现者,它只是一个代理,它的真正实现者是transportAction.本篇就对action及transportAction的实现做一个简单的分析, elasticsearch中的绝大部分操作都是通过相应的action,这些action在action包中.它的结构如下图所示: 上图是action包的部分截图,这里面对应着各个功能

springboot使用elasticsearch的客户端操作eslaticsearch

一  ES客户端 ES提供多种不同的客户端: 1.TransportClient ES提供的传统客户端,官方计划8.0版本删除此客户端. 2.RestClient RestClient是官方推荐使用的,它包括两种:Java Low Level REST Client和 Java High Level REST Client. ES在6.0之后提供 Java High Level REST Client, 两种客户端官方更推荐使用 Java High Level REST Client,不过当前它

ElasticSearch的客户端操作

实际开发中,主要由三种方式可以作为elasticsearch服务的客户端: 1.elasticsearch-head插件: 2.使用elasticsearch提供的Restful接口直接访问: 3.使用elasticsearch提供的API进行访问: 使用Postman工具进行Restful接口访问(下载地址:https://www.postman.com/) 1.elasticsearch的接口语法 curl ‐X<VERB> '<PROTOCOL>://<HOST>

Kafka客户端二次封装扩展总体设计

前言背景 消息系统经过多年使用和运维管理平台开发迭代,能较好支持支撑业务发展,公司主流语言为java,但缺乏一个基于Kafka二次封装简单好用的java客户端.遇到问题如下所示: 使用好kafka客户端对业务要求高,非专业技术方向很难有精力全面掌握 异常情况会catch不全 客户端生产消息及双活机房容灾缺失 集群升级难度增加,因为无法全面及时掌握客户端信息(kafka版本.groupid) 不支持动态配置更新,业务使用错误及引发的潜在故障无法及时修正,例如Producer写入倾斜导致磁盘报警,参