Spring cloud 查询返回广告创意实例代码
根据三个维度继续过滤
在上一节中我们实现了根据流量信息过滤的代码,但是我们的条件有可能是多条件一起传给我们的检索服务的,本节我们继续实现根据推广单元的三个维度条件的过滤。
在SearchImpl类中添加过滤方法
publicclassSearchImplimplementsISearch{ @Override publicSearchResponsefetchAds(SearchRequestrequest){ ... //根据三个维度过滤 if(featureRelation==FeatureRelation.AND){ filterKeywordFeature(adUnitIdSet,keywordFeature); filterHobbyFeature(adUnitIdSet,hobbyFeatrue); filterDistrictFeature(adUnitIdSet,districtFeature); targetUnitIdSet=adUnitIdSet; }else{ getOrRelationUnitIds(adUnitIdSet,keywordFeature,hobbyFeatrue,districtFeature); } } returnnull; }
定义三个方法实现过滤
/** *获取三个维度各自满足时的广告id */ privateSetgetOrRelationUnitIds(Set adUnitIdsSet, KeywordFeaturekeywordFeature, HobbyFeatruehobbyFeatrue, DistrictFeaturedistrictFeature){ if(CollectionUtils.isEmpty(adUnitIdsSet))returnCollections.EMPTY_SET; //我们在处理的时候,需要对副本进行处理,大家可以考虑一下为什么需要这么做? Set keywordUnitIdSet=newHashSet<>(adUnitIdsSet); Set hobbyUnitIdSet=newHashSet<>(adUnitIdsSet); Set districtUnitIdSet=newHashSet<>(adUnitIdsSet); filterKeywordFeature(keywordUnitIdSet,keywordFeature); filterHobbyFeature(hobbyUnitIdSet,hobbyFeatrue); filterDistrictFeature(districtUnitIdSet,districtFeature); //返回它们的并集 returnnewHashSet<>( CollectionUtils.union( CollectionUtils.union(keywordUnitIdSet,hobbyUnitIdSet), districtUnitIdSet ) ); } /** *根据传递的关键词过滤 */ privatevoidfilterKeywordFeature(Collection adUnitIds,KeywordFeaturekeywordFeature){ if(CollectionUtils.isEmpty(adUnitIds))return; if(CollectionUtils.isNotEmpty(keywordFeature.getKeywords())){ //如果存在需要过滤的关键词,查找索引实例对象进行过滤处理 CollectionUtils.filter( adUnitIds, adUnitId->IndexDataTableUtils.of(UnitKeywordIndexAwareImpl.class) .match(adUnitId,keywordFeature.getKeywords()) ); } } /** *根据传递的兴趣信息过滤 */ privatevoidfilterHobbyFeature(Collection adUnitIds,HobbyFeatruehobbyFeatrue){ if(CollectionUtils.isEmpty(adUnitIds))return; //如果存在需要过滤的兴趣,查找索引实例对象进行过滤处理 if(CollectionUtils.isNotEmpty(hobbyFeatrue.getHobbys())){ CollectionUtils.filter( adUnitIds, adUnitId->IndexDataTableUtils.of(UnitHobbyIndexAwareImpl.class) .match(adUnitId,hobbyFeatrue.getHobbys()) ); } } /** *根据传递的地域信息过滤 */ privatevoidfilterDistrictFeature(Collection adUnitIds,DistrictFeaturedistrictFeature){ if(CollectionUtils.isEmpty(adUnitIds))return; //如果存在需要过滤的地域信息,查找索引实例对象进行过滤处理 if(CollectionUtils.isNotEmpty(districtFeature.getProvinceAndCities())){ CollectionUtils.filter( adUnitIds, adUnitId->{ returnIndexDataTableUtils.of(UnitDistrictIndexAwareImpl.class) .match(adUnitId,districtFeature.getProvinceAndCities()); } ); } }
根据推广单元id获取推广创意
我们知道,推广单元和推广创意的关系是多对多,从上文我们查询到了推广单元ids,接下来我们实现根据推广单元id获取推广创意的代码,let'scode.
首先,我们需要在com.sxzhongf.ad.index.creative_relation_unit.CreativeRelationUnitIndexAwareImpl关联索引中查到推广创意的ids
/** *通过推广单元id获取推广创意id */ publicListselectAdCreativeIds(List unitIndexObjects){ if(CollectionUtils.isEmpty(unitIndexObjects))returnCollections.emptyList(); //获取要返回的广告创意ids List result=newArrayList<>(); for(AdUnitIndexObjectunitIndexObject:unitIndexObjects){ //根据推广单元id获取推广创意 Set adCreativeIds=unitRelationCreativeMap.get(unitIndexObject.getUnitId()); if(CollectionUtils.isNotEmpty(adCreativeIds))result.addAll(adCreativeIds); } returnresult; }
然后得到了推广创意的idlist后,我们在创意索引实现类com.sxzhongf.ad.index.creative.CreativeIndexAwareImpl中定义根据ids查询创意的方法。
/** *根据ids获取创意list */ publicListfindAllByIds(Collection ids){ if(CollectionUtils.isEmpty(ids))returnCollections.emptyList(); List result=newArrayList<>(); for(Longid:ids){ CreativeIndexObjectobject=get(id); if(null!=object) result.add(object); } returnresult; }
自此,我们已经得到了想要的推广单元和推广创意,因为推广单元包含了推广计划,所以我们想要的数据已经全部可以获取到了,接下来,我们还得过滤一次当前我们查询到的数据的状态,因为有的数据,我们可能已经进行过逻辑删除了,因此还需要判断获取的数据是否有效。在SearchImpl类中实现。
/** *根据状态信息过滤数据 */ privatevoidfilterAdUnitAndPlanStatus(ListunitIndexObjects,CommonStatusstatus){ if(CollectionUtils.isEmpty(unitIndexObjects))return; //同时判断推广单元和推广计划的状态 CollectionUtils.filter( unitIndexObjects, unitIndexObject->unitIndexObject.getUnitStatus().equals(status.getStatus())&& unitIndexObject.getAdPlanIndexObject().getPlanStatus().equals(status.getStatus()) ); }
在SearchImpl中我们实现广告创意的查询.
... //获取推广计划对象list ListunitIndexObjects=IndexDataTableUtils.of(AdUnitIndexAwareImpl.class).fetch(adUnitIdSet); //根据状态过滤数据 filterAdUnitAndPlanStatus(unitIndexObjects,CommonStatus.VALID); //获取推广创意idlist List creativeIds=IndexDataTableUtils.of(CreativeRelationUnitIndexAwareImpl.class) .selectAdCreativeIds(unitIndexObjects); //根据推广创意ids获取推广创意 List creativeIndexObjects=IndexDataTableUtils.of(CreativeIndexAwareImpl.class) ...
根据广告位adslot实现对创意数据的过滤
因为我们的广告位是有不同的大小,不同的类型,因此,我们在获取到所有符合我们查询维度以及流量类型的条件后,还需要针对不同的广告位来展示不同的广告创意信息。
/** *根据广告位类型以及参数获取展示的合适广告信息 * *@paramcreativeIndexObjects所有广告创意 *@paramwidth广告位width *@paramheight广告位height */ privatevoidfilterCreativeByAdSlot(ListcreativeIndexObjects, Integerwidth, Integerheight, List type){ if(CollectionUtils.isEmpty(creativeIndexObjects))return; CollectionUtils.filter( creativeIndexObjects, creative->{ //审核状态必须是通过 returncreative.getAuditStatus().equals(CommonStatus.VALID.getStatus()) &&creative.getWidth().equals(width) &&creative.getHeight().equals(height) &&type.contains(creative.getType()); } ); }
组建搜索返回对象
正常业务场景中,同一个广告位可以展示多个广告信息,也可以只展示一个广告信息,这个需要根据具体的业务场景来做不同的处理,本次为了演示方便,会从返回的创意列表中随机选择一个创意广告信息进行展示,当然大家也可以根据业务类型,设置不同的优先级或者权重值来进行广告选择。
/** *从创意列表中随机获取一条创意广告返回出去 * *@paramcreativeIndexObjects创意广告list */ privateListbuildCreativeResponse(List creativeIndexObjects){ if(CollectionUtils.isEmpty(creativeIndexObjects))returnCollections.EMPTY_LIST; //随机获取一个广告创意,也可以实现优先级排序,也可以根据权重值等等,具体根据业务 CreativeIndexObjectrandomObject=creativeIndexObjects.get( Math.abs(newRandom().nextInt())%creativeIndexObjects.size() ); //List result=newArrayList<>(); //result.add(SearchResponse.convert(randomObject)); returnCollections.singletonList( SearchResponse.convert(randomObject) ); }
完整的请求过滤实现方法:
@Service @Slf4j publicclassSearchImplimplementsISearch{ @Override publicSearchResponsefetchAds(SearchRequestrequest){ //获取请求广告位信息 ListadSlotList=request.getRequestInfo().getAdSlots(); //获取三个Feature信息 KeywordFeaturekeywordFeature=request.getFeatureInfo().getKeywordFeature(); HobbyFeatruehobbyFeatrue=request.getFeatureInfo().getHobbyFeatrue(); DistrictFeaturedistrictFeature=request.getFeatureInfo().getDistrictFeature(); //Feature关系 FeatureRelationfeatureRelation=request.getFeatureInfo().getRelation(); //构造响应对象 SearchResponseresponse=newSearchResponse(); Map >adSlotRelationAds=response.getAdSlotRelationAds(); for(AdSlotadSlot:adSlotList){ Set targetUnitIdSet; //根据流量类型从缓存中获取初始广告信息 Set adUnitIdSet=IndexDataTableUtils.of( AdUnitIndexAwareImpl.class ).match(adSlot.getPositionType()); //根据三个维度过滤 if(featureRelation==FeatureRelation.AND){ filterKeywordFeature(adUnitIdSet,keywordFeature); filterHobbyFeature(adUnitIdSet,hobbyFeatrue); filterDistrictFeature(adUnitIdSet,districtFeature); targetUnitIdSet=adUnitIdSet; }else{ targetUnitIdSet=getOrRelationUnitIds(adUnitIdSet,keywordFeature,hobbyFeatrue,districtFeature); } //获取推广计划对象list List unitIndexObjects=IndexDataTableUtils.of(AdUnitIndexAwareImpl.class) .fetch(targetUnitIdSet); //根据状态过滤数据 filterAdUnitAndPlanStatus(unitIndexObjects,CommonStatus.VALID); //获取推广创意idlist List creativeIds=IndexDataTableUtils.of(CreativeRelationUnitIndexAwareImpl.class) .selectAdCreativeIds(unitIndexObjects); //根据推广创意ids获取推广创意 List creativeIndexObjects=IndexDataTableUtils.of(CreativeIndexAwareImpl.class) .fetch(creativeIds); //根据广告位adslot实现对创意数据的过滤 filterCreativeByAdSlot(creativeIndexObjects,adSlot.getWidth(),adSlot.getHeight(),adSlot.getType()); //一个广告位可以展示多个广告,也可以仅展示一个广告,具体根据业务来定 adSlotRelationAds.put( adSlot.getAdSlotCode(), buildCreativeResponse(creativeIndexObjects) ); } returnresponse; } ...
检索服务对外提供
暴露API接口
上文中,我们实现了检索服务的核心逻辑,接下来,我们需要对外暴露我们的广告检索服务接口,在SearchController中提供:
@PostMapping("/fetchAd") publicSearchResponsefetchAdCreative(@RequestBodySearchRequestrequest){ log.info("ad-serach:fetchAd->{}",JSON.toJSONString(request)); returnsearch.fetchAds(request); }
实现API网关配置
zuul: routes: sponsor:#在路由中自定义服务路由名称 path:/ad-sponsor/** serviceId:mscx-ad-sponsor#微服务name strip-prefix:false search:#在路由中自定义服务路由名称 path:/ad-search/** serviceId:mscx-ad-search#微服务name strip-prefix:false prefix:/gateway/api strip-prefix:true#不对prefix:/gateway/api设置的路径进行截取,默认转发会截取掉配置的前缀
以上就是本次分享的全部知识点内容,感谢大家对毛票票的支持