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){
SettargetUnitIdSet;
//根据流量类型从缓存中获取初始广告信息
SetadUnitIdSet=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
ListunitIndexObjects=IndexDataTableUtils.of(AdUnitIndexAwareImpl.class)
.fetch(targetUnitIdSet);
//根据状态过滤数据
filterAdUnitAndPlanStatus(unitIndexObjects,CommonStatus.VALID);
//获取推广创意idlist
ListcreativeIds=IndexDataTableUtils.of(CreativeRelationUnitIndexAwareImpl.class)
.selectAdCreativeIds(unitIndexObjects);
//根据推广创意ids获取推广创意
ListcreativeIndexObjects=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设置的路径进行截取,默认转发会截取掉配置的前缀
以上就是本次分享的全部知识点内容,感谢大家对毛票票的支持