沧州三亚菏泽经济预测自然
投稿投诉
自然科学
知识物理
化学生物
地理解释
预测理解
本质社会
人类现象
行为研究
经济政治
心理结构
关系指导
人文遗产
菏泽德阳
山西湖州
宝鸡上海
茂名内江
三亚信阳
长春北海
西安安徽
黄石烟台
沧州湛江
肇庆鹤壁
六安韶关
成都钦州

MyBatisPlus同款ElasticsearchORM框

7月15日 阴阳狱投稿
  使用过SpringData操作ES的小伙伴应该有所了解,它只能实现一些非常基本的数据管理工作,一旦遇到稍微复杂点的查询,基本都要依赖ES官方提供的RestHighLevelClient,SpringData只是在其基础上进行了简单的封装。最近发现一款更优雅的ESORM框架EasyEs,使用它能像MyBatisPlus一样操作ES,今天就以mall项目中的商品搜索功能为例,来聊聊它的使用!EasyEs简介
  EasyEs(简称EE)是一款基于Elasticsearch(简称ES)官方提供的RestHighLevelClient打造的ORM开发框架,在RestHighLevelClient的基础上,只做增强不做改变,为简化开发、提高效率而生。EE和MybatisPlus(简称MP)的用法非常相似,如果你之前使用过MP的话,应该能很快上手EE。EE的理念是:把简单、易用、方便留给用户,把复杂留给框架。
  EE的主要特性如下:全自动索引托管:开发者无需关心索引的创建、更新及数据迁移等繁琐步骤,框架能自动完成。屏蔽语言差异:开发者只需要会MySQL的语法即可使用ES。代码量极少:与直接使用官方提供的RestHighLevelClient相比,相同的查询平均可以节省35倍的代码量。零魔法值:字段名称直接从实体中获取,无需手写。零额外学习成本:开发者只要会国内最受欢迎的MybatisPlus用法,即可无缝迁移至EE。MySQL与EasyEs语法对比
  首先我们来对MySQL、EasyEs和RestHighLevelClient的语法做过对比,来快速学习下EasyEs的语法。
  MySQL
  EasyEs
  esDSLesjavaapi
  and
  and
  must
  or
  or
  should
  eq
  term
  !
  ne
  boolQueryBuilder。mustNot(queryBuilder)
  gt
  QueryBuilders。rangeQuery(esfield)。gt()
  ge
  。rangeQuery(esfield)。gte()
  lt
  。rangeQuery(esfield)。lt()
  le
  。rangeQuery(esfield)。lte()
  likefield
  like
  QueryBuilders。wildcardQuery(field,value)
  notlikefield
  notLike
  mustnotwildcardQuery(field,value)
  likefield
  likeLeft
  QueryBuilders。wildcardQuery(field,value)
  likefield
  likeRight
  QueryBuilders。wildcardQuery(field,value)
  between
  between
  QueryBuilders。rangeQuery(esfield)。from(xx)。to(xx)
  notBetween
  notBetween
  mustnotQueryBuilders。rangeQuery(esfield)。from(xx)。to(xx)
  isnull
  isNull
  mustnotQueryBuilders。existsQuery(field)
  isnotNull
  isNotNull
  QueryBuilders。existsQuery(field)
  in
  in
  QueryBuilders。termsQuery(xxesfield,xx)
  notin
  notIn
  mustnotQueryBuilders。termsQuery(xxesfield,xx)
  groupby
  groupBy
  AggregationBuilders。terms()
  orderby
  orderBy
  fieldSortBuilder。order(ASCDESC)
  min
  min
  AggregationBuilders。min
  max
  max
  AggregationBuilders。max
  avg
  avg
  AggregationBuilders。avg
  sum
  sum
  AggregationBuilders。sum
  orderbyxxxasc
  orderByAsc
  fieldSortBuilder。order(SortOrder。ASC)
  orderbyxxxdesc
  orderByDesc
  fieldSortBuilder。order(SortOrder。DESC)
  match
  matchQuery
  matchPhrase
  QueryBuilders。matchPhraseQuery
  matchPrefix
  QueryBuilders。matchPhrasePrefixQuery
  queryStringQuery
  QueryBuilders。queryStringQuery
  select
  matchAllQuery
  QueryBuilders。matchAllQuery()
  highLight
  HighlightBuilder。Field
  。。。
  。。。
  。。。集成及配置
  接下来把EasyEs集成到项目中配置下就可以使用了。首先需要在pom。xml中添加EasyEs的相关依赖;dependencygroupIdcn。easyesgroupIdeasyesbootstarterartifactIdversion1。0。2versiondependency
  由于底层使用了ES官方提供的RestHighLevelClient,这里ES的相关依赖版本需要统一下,这里使用的ES客户端版本为7。14。0,ES版本为7。17。3;dependencyManagementdependenciesdependencygroupIdorg。elasticsearch。clientgroupIdelasticsearchresthighlevelclientartifactIdversion7。14。0versiondependencydependencygroupIdorg。elasticsearchgroupIdelasticsearchartifactIdversion7。14。0versiondependencydependenciesdependencyManagement
  再修改配置文件application。yml对EasyEs进行配置。easyes:是否开启EE自动配置enable:trueES连接地址端口address:localhost:9200关闭自带bannerbanner:false
  添加EasyEs的Java配置,使用EsMapperScan配置好EasyEs的Mapper接口和文档对象路径,如果你使用了MyBatisPlus的话,需要和它的扫描路径区分开来。EasyEs配置类Createdbymacroon2022916。ConfigurationEsMapperScan(com。macro。mall。tiny。easyes)publicclassEasyEsConfig{}使用
  EasyEs集成和配置完成后,就可以开始使用了。这里还是以mall项目的商品搜索功能为例,聊聊EasyEs的使用,SpringData的实现方式可以参考Elasticsearch项目实战,商品搜索功能设计与实现!。注解的使用
  下面我们来学习下EasyEs中注解的使用。首先我们需要创建文档对象EsProduct,然后给类和字段添加上EasyEs的注解;搜索商品的信息Createdbymacroon2018619。DataEqualsAndHashCodeIndexName(valuepms,shardsNum1,replicasNum0)publicclassEsProductimplementsSerializable{privatestaticfinallongserialVersionUID1L;IndexId(typeIdType。CUSTOMIZE)privateLIndexField(fieldTypeFieldType。KEYWORD)privateStringproductSn;privateLongbrandId;IndexField(fieldTypeFieldType。KEYWORD)privateStringbrandNprivateLongproductCategoryId;IndexField(fieldTypeFieldType。KEYWORD)privateStringproductCategoryNprivateSIndexField(fieldTypeFieldType。TEXT,analyzerikmaxword)privateSIndexField(fieldTypeFieldType。TEXT,analyzerikmaxword)privateStringsubTIndexField(fieldTypeFieldType。TEXT,analyzerikmaxword)privateSprivateBigDprivateIprivateIntegernewSprivateIntegerrecommandSprivateIprivateIntegerpromotionTprivateIIndexField(fieldTypeFieldType。NESTED,nestedClassEsProductAttributeValue。class)privateListEsProductAttributeValueattrValueLScoreprivateF}EsProduct中的注解具体说明如下:
  注解名称
  用途
  参数
  IndexName
  索引名注解
  value:指定索引名;shardsNum:分片数;replicasNum:副本数
  IndexId
  ES主键注解
  type:指定注解类型,CUSTOMIZE表示自定义
  IndexField
  ES字段注解
  fieldType:字段在索引中的类型;analyzer:索引文档时用的分词器;nestedClass:嵌套类
  Score
  得分注解
  decimalPlaces:得分保留小数位,实体类中被作为ES查询得分返回的字段使用EsProduct中嵌套类型EsProductAttributeValue的代码如下。搜索商品的属性信息Createdbymacroon2018627。DataEqualsAndHashCodepublicclassEsProductAttributeValueimplementsSerializable{privatestaticfinallongserialVersionUID1L;IndexField(fieldTypeFieldType。LONG)privateLIndexField(fieldTypeFieldType。KEYWORD)privateLongproductAttributeId;属性值IndexField(fieldTypeFieldType。KEYWORD)privateS属性参数:0规格;1参数IndexField(fieldTypeFieldType。INTEGER)privateI属性名称IndexField(fieldTypeFieldType。KEYWORD)privateS}商品信息维护
  下面我们来实现几个简单的商品信息维护接口,包括商品信息的导入、创建和删除。首先我们需要定义一个Mapper,继承BaseEsM商品ES操作类Createdbymacroon2018619。publicinterfaceEsProductMapperextendsBaseEsMapperEsProduct{}
  然后在Service实现类中直接使用EsProductMapper内置方法实现即可,是不是和MyBatisPlus的用法一致?搜索商品管理Service实现类Createdbymacroon2018619。ServicepublicclassEsProductServiceImplimplementsEsProductService{AutowiredprivateEsProductDaoproductDAutowiredprivateEsProductMapperesProductMOverridepublicintimportAll(){ListEsProductesProductListproductDao。getAllEsProductList(null);returnesProductMapper。insertBatch(esProductList);}Overridepublicvoiddelete(Longid){esProductMapper。deleteById(id);}OverridepublicEsProductcreate(Longid){EsPListEsProductesProductListproductDao。getAllEsProductList(id);if(esProductList。size()0){resultesProductList。get(0);esProductMapper。insert(result);}}Overridepublicvoiddelete(ListLongids){if(!CollectionUtils。isEmpty(ids)){esProductMapper。deleteBatchIds(ids);}}}简单商品搜索
  下面我们来实现一个最简单的商品搜索,分页搜索商品名称、副标题、关键词中包含指定关键字的商品。通过QueryWrapper来构造查询条件,然后使用Mapper中的方法来进行查询,使用过MyBatisPlus的小伙伴应该很熟悉了;搜索商品管理Service实现类Createdbymacroon2018619。ServicepublicclassEsProductServiceImplimplementsEsProductService{AutowiredprivateEsProductMapperesProductMOverridepublicPageInfoEsProductsearch(Stringkeyword,IntegerpageNum,IntegerpageSize){LambdaEsQueryWrapperEsProductwrappernewLambdaEsQueryWrapper();if(StrUtil。isEmpty(keyword)){wrapper。matchAllQuery();}else{wrapper。multiMatchQuery(keyword,EsProduct::getName,EsProduct::getSubTitle,EsProduct::getKeywords);}returnesProductMapper。pageQuery(wrapper,pageNum,pageSize);}}
  使用Swagger访问接口后,可以在控制台输出查看生成的DSL语句
  把DSL语句直接复制Kibana中即可执行查看结果了,这和我们手写DSL语句没什么两样的。
  综合商品搜索
  下面我们来实现一个复杂的商品搜索,涉及到过滤、不同字段匹配权重不同以及可以进行排序。首先来说需求,按输入的关键字搜索商品名称(权重10)、副标题(权重5)和关键词(权重2),可以按品牌和分类进行筛选,可以有5种排序方式,默认按相关度进行排序,看下接口文档有助于理解;
  这个功能之前使用SpringData来实现非常复杂,使用EasyEs来实现确实简洁不少,下面是使用EasyEs的实现方式;搜索商品管理Service实现类Createdbymacroon2018619。ServicepublicclassEsProductServiceImplimplementsEsProductService{AutowiredprivateEsProductMapperesProductMOverridepublicPageInfoEsProductsearch(Stringkeyword,LongbrandId,LongproductCategoryId,IntegerpageNum,IntegerpageSize,Integersort){LambdaEsQueryWrapperEsProductwrappernewLambdaEsQueryWrapper();过滤if(brandId!nullproductCategoryId!null){if(brandId!null){wrapper。eq(EsProduct::getBrandId,brandId);}if(productCategoryId!null){wrapper。eq(EsProduct::getProductCategoryId,productCategoryId)。enableMust2Filter(true);}}搜索if(StrUtil。isEmpty(keyword)){wrapper。matchAllQuery();}else{wrapper。and(ii。match(EsProduct::getName,keyword,10f)。or()。match(EsProduct::getSubTitle,keyword,5f)。or()。match(EsProduct::getKeywords,keyword,2f));}排序if(sort1){按新品从新到旧wrapper。orderByDesc(EsProduct::getId);}elseif(sort2){按销量从高到低wrapper。orderByDesc(EsProduct::getSale);}elseif(sort3){按价格从低到高wrapper。orderByAsc(EsProduct::getPrice);}elseif(sort4){按价格从高到低wrapper。orderByDesc(EsProduct::getPrice);}else{按相关度wrapper。sortByScore(SortOrder。DESC);}returnesProductMapper。pageQuery(wrapper,pageNum,pageSize);}}再对比下之前使用SpringData的实现方式,没有QueryWrapper来构造条件,还要硬编码字段名称,确实优雅了不少!
  相关商品推荐
  当我们查看相关商品的时候,一般底部会有一些商品推荐,这里简单来实现下。首先来说下需求,可以根据指定商品的ID来查找相关商品,看下接口文档有助于理解;
  这里我们的实现原理是这样的:首先根据ID获取指定商品信息,然后以指定商品的名称、品牌和分类来搜索商品,并且要过滤掉当前商品,调整搜索条件中的权重以获取最好的匹配度;使用EasyEs来实现依旧是那么简洁!搜索商品管理Service实现类Createdbymacroon2018619。ServicepublicclassEsProductServiceImplimplementsEsProductService{AutowiredprivateEsProductMapperesProductMOverridepublicPageInfoEsProductrecommend(Longid,IntegerpageNum,IntegerpageSize){LambdaEsQueryWrapperEsProductwrappernewLambdaEsQueryWrapper();ListEsProductesProductListproductDao。getAllEsProductList(id);if(esProductList。size()0){EsProductesProductesProductList。get(0);StringkeywordesProduct。getName();LongbrandIdesProduct。getBrandId();LongproductCategoryIdesProduct。getProductCategoryId();用于过滤掉相同的商品wrapper。ne(EsProduct::getId,id);根据商品标题、品牌、分类进行搜索wrapper。and(ii。match(EsProduct::getName,keyword,8f)。or()。match(EsProduct::getSubTitle,keyword,2f)。or()。match(EsProduct::getKeywords,keyword,2f)。or()。match(EsProduct::getBrandId,brandId,5f)。or()。match(EsProduct::getProductCategoryId,productCategoryId,3f));returnesProductMapper。pageQuery(wrapper,pageNum,pageSize);}returnesProductMapper。pageQuery(wrapper,pageNum,pageSize);}}聚合搜索商品相关信息
  在搜索商品时,经常会有一个筛选界面来帮助我们找到想要的商品,这里我们来简单实现下。首先来说下需求,可以根据搜索关键字获取到与关键字匹配商品相关的分类、品牌以及属性,下面这张图有助于理解;
  这里我们可以使用ES的聚合来实现,搜索出相关商品,聚合出商品的品牌、商品的分类以及商品的属性,只要出现次数最多的前十个即可;由于EasyEs目前只用groupBy实现了简单的聚合,对于我们这种有嵌套对象的聚合无法支持,所以需要使用RestHighLevelClient来实现,如果你对照之前的SpringData实现方式的话,可以发现用法差不多,看样子SpringData只是做了简单的封装而已。搜索商品管理Service实现类Createdbymacroon2018619。ServicepublicclassEsProductServiceImplimplementsEsProductService{AutowiredprivateEsProductMapperesProductMOverridepublicEsProductRelatedInfosearchRelatedInfo(Stringkeyword){SearchRequestsearchRequestnewSearchRequest();searchRequest。indices(pms);SearchSourceBuilderbuildernewSearchSourceBuilder();搜索条件if(StrUtil。isEmpty(keyword)){builder。query(QueryBuilders。matchAllQuery());}else{builder。query(QueryBuilders。multiMatchQuery(keyword,name,subTitle,keywords));}聚合搜索品牌名称builder。aggregation(AggregationBuilders。terms(brandNames)。field(brandName));集合搜索分类名称builder。aggregation(AggregationBuilders。terms(productCategoryNames)。field(productCategoryName));聚合搜索商品属性,去除type1的属性AbstractAggregationBuilderNestedAggregationBuilderaggregationBuilderAggregationBuilders。nested(allAttrValues,attrValueList)。subAggregation(AggregationBuilders。filter(productAttrs,QueryBuilders。termQuery(attrValueList。type,1))。subAggregation(AggregationBuilders。terms(attrIds)。field(attrValueList。productAttributeId)。subAggregation(AggregationBuilders。terms(attrValues)。field(attrValueList。value))。subAggregation(AggregationBuilders。terms(attrNames)。field(attrValueList。name))));builder。aggregation(aggregationBuilder);searchRequest。source(builder);try{SearchResponsesearchResponseesProductMapper。search(searchRequest,RequestOptions。DEFAULT);returnconvertProductRelatedInfo(searchResponse);}catch(IOExceptione){e。printStackTrace();}}将返回结果转换为对象privateEsProductRelatedInfoconvertProductRelatedInfo(SearchResponseresponse){EsProductRelatedInfoproductRelatedInfonewEsProductRelatedInfo();MapString,AggregationaggregationMapresponse。getAggregations()。asMap();设置品牌AggregationbrandNamesaggregationMap。get(brandNames);ListStringbrandNameListnewArrayList();for(inti0;i((Terms)brandNames)。getBuckets()。size();i){brandNameList。add(((Terms)brandNames)。getBuckets()。get(i)。getKeyAsString());}productRelatedInfo。setBrandNames(brandNameList);设置分类AggregationproductCategoryNamesaggregationMap。get(productCategoryNames);ListStringproductCategoryNameListnewArrayList();for(inti0;i((Terms)productCategoryNames)。getBuckets()。size();i){productCategoryNameList。add(((Terms)productCategoryNames)。getBuckets()。get(i)。getKeyAsString());}productRelatedInfo。setProductCategoryNames(productCategoryNameList);设置参数AggregationproductAttrsaggregationMap。get(allAttrValues);L?extendsTerms。BucketattrIds((ParsedStringTerms)((ParsedFilter)((ParsedNested)productAttrs)。getAggregations()。get(productAttrs))。getAggregations()。get(attrIds))。getBuckets();ListEsProductRelatedInfo。ProductAttrattrListnewArrayList();for(Terms。BucketattrId:attrIds){EsProductRelatedInfo。ProductAttrattrnewEsProductRelatedInfo。ProductAttr();attr。setAttrId(Long。parseLong((String)attrId。getKey()));ListStringattrValueListnewArrayList();L?extendsTerms。BucketattrValues((ParsedStringTerms)attrId。getAggregations()。get(attrValues))。getBuckets();L?extendsTerms。BucketattrNames((ParsedStringTerms)attrId。getAggregations()。get(attrNames))。getBuckets();for(Terms。BucketattrValue:attrValues){attrValueList。add(attrValue。getKeyAsString());}attr。setAttrValues(attrValueList);if(!CollectionUtils。isEmpty(attrNames)){StringattrNameattrNames。get(0)。getKeyAsString();attr。setAttrName(attrName);}attrList。add(attr);}productRelatedInfo。setProductAttrs(attrList);returnproductRelatedI}}总结
  今天将之前的使用SpringData的商品搜索案例使用EasyEs改写了一下,确实使用EasyEs更简单,但是对于复杂的聚合搜索功能,两者都需要使用原生的RestHighLevelClient用法来实现。使用EasyEs来操作ES确实足够优雅,它类似MyBatisPlus的用法能大大降低我们的学习成本,快速完成开发工作!
投诉 评论 转载

任性媳妇与霸王婆婆过招我任性是举家上下都知道的,什么叫任性就是你得听我的,我说得就对,你、你、说你呢得围着我转。婆婆是家里的霸王,霸王是什么,不知道吧就是女皇,她老人家高高在上,小一辈的我们俯……欧洲市场遭遇黑色星期五股债汇三杀,斯托克600跌入熊市欧洲股市遭遇黑色星期五。9月23日,欧洲股市盘中全线走弱,且跌幅仍在扩大。截至发稿时,德国DAX指数日内跌幅达2。49,法国CAC40指数跌2。18,英国富时100……MyBatisPlus同款ElasticsearchORM框使用过SpringData操作ES的小伙伴应该有所了解,它只能实现一些非常基本的数据管理工作,一旦遇到稍微复杂点的查询,基本都要依赖ES官方提供的RestHighLevelCl……三角肌后束训练的方法三角肌后束就是背部的一块,这个地方要是有肌肉的话,那么也是男人的小小心愿,要是后背部位能够得到肌肉的锻炼,这样的男人也觉得自己非常的自豪,还很成熟,不会看起来柔柔弱弱的,三角肌……电脑族有哪些食疗养肝方法电脑已经成为我们工作、学习、以及业余娱乐、查看资讯新闻、获得信息的一个必备工具,我们在电脑前面的时间也会越来越长中医曰:久视伤肝,久坐伤骨。电脑一族长期坐在电脑前,眼睛盯着显示……春姐姐的绿裙子淘气的冬弟弟已经被春姐姐赶走。今天,春未了迎接自己的到来,特意打扮得漂漂亮亮的,她穿着一条绿而长的裙子。这条绿裙子可真怪,它一飘到哪儿,哪儿的花草树木就会恢复生机,不再低……风暴英雄为什么不火独特的游戏机制既是亮点也最大的风暴英雄这款游戏是于2015年6月3日正式上线的,是由暴雪公司开发的一款MOBA类游戏。风暴英雄无论是画质还是操作,说句实话都还是非常不错的,但可惜的是风暴英雄就是火不起来。那……最适合草根的五个低成本创业项目看起来不起眼却受年生活中近年来常常有一些人被称作草根,那么何为草根呢?这里说的是一些年轻人,一些不知道努力浪费青春的年轻人。有人说:能成功,谁愿意做一个草根?其实在很多人的眼里,年轻人创业不容易……斯诺克夺冠榜单公布!丁俊晖无缘,赵心童垫底,00后小将送来惊北京时间4月23日,斯诺克世锦赛正在英国如火如荼地进行之中。随着夺冠热门特鲁姆普以10比4大比分,战胜伊朗名将瓦菲之后,2022年斯诺克世锦赛的16强名单也全部产生。中国军团派……坐镇造句用坐镇造句大全一百二十一、首秀中他坐镇中路眼观四方,展现了自己组织大师的绝活。一百二十二、泮溪酒家、陈李济、皇上皇等多家老字号“坐镇”现场,展示老字号传统工艺及产品。一百二十三、……比较令人讨厌的十句话1。日常生活:随便问老婆想去哪里随便;问老婆想吃什么随便什么事都丢给你做,最后在鸡蛋里挑骨头,真的很不爽!2。领导讲话:下面我简单说两句这个之前就被许多网友调……更年期女性心理敏感吗更年期是一生一个必经阶段,无聊男女都会有更年期,就女性而言,患上更年期的妇女卵巢功能衰退所产生的神经内分泌暂时性失调与不能适应,产生一些自觉症状。如头晕、头痛、耳鸣、易激动、思……
宝宝得空调病的症状有哪些官宣胡歌万茜雷佳音李光洁童瑶等将出席胃不好怎么办?医生建议,要尽量少吃3种食物,并且要多做三件事离开甘肃,到达中卫新生儿洗澡水温多少合适企业品牌的战略选择大特造句用大特造句大全dnf嘉年华晚会,110级版本预热,几个重要的改变给老板娘送什么礼物合适切记把这个秘诀看遍电动牙刷哪个牌子好?双十二权威选购排行榜单中国河南南阳方城龙凤山景区民俗文化节即将震撼上演华为,OPPO,真我手机,1500元档大对决

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找