1.定义流量类型
广告位的类型对应的数字分别是1,2,4,8,16,很显然这是一个二进制的编排,这样定义的目的是为了能够根据位运算加快检索速度。
package com.imooc.ad.index.adunit;
public class AdUnitConstants {
public static class POSITION_TYPE {
public static final int KAIPING = 1;
public static final int TIEPIAN = 2;
public static final int TIEPIAN_MIDDLE = 4;
public static final int TIEPIAN_PAUSE = 8;
public static final int TIEPIAN_POST = 16;
}
}
2.AdUnitObject 中实现判断
package com.imooc.ad.index.adunit;
import com.imooc.ad.index.adplan.AdPlanObject;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class AdUnitObject {
private Long unitId;
private Integer unitStatus;
private Integer positionType;
private Long planId;
private AdPlanObject adPlanObject;
void update(AdUnitObject newObject) {
if (null != newObject.getUnitId()) {
this.unitId = newObject.getUnitId();
}
if (null != newObject.getUnitStatus()) {
this.unitStatus = newObject.getUnitStatus();
}
if (null != newObject.getPositionType()) {
this.positionType = newObject.getPositionType();
}
if (null != planId) {
this.planId = newObject.getPlanId();
}
if (null != newObject.getAdPlanObject()) {
this.adPlanObject = newObject.getAdPlanObject();
}
}
private static boolean isKaiPing(int positionType) {
return (positionType & AdUnitConstants.POSITION_TYPE.KAIPING) > 0;
}
private static boolean isTiePian(int positionType) {
return (positionType & AdUnitConstants.POSITION_TYPE.TIEPIAN) > 0;
}
private static boolean isTiePianMiddle(int positionType) {
return (positionType & AdUnitConstants.POSITION_TYPE.TIEPIAN_MIDDLE) > 0;
}
private static boolean isTiePianPause(int positionType) {
return (positionType & AdUnitConstants.POSITION_TYPE.TIEPIAN_PAUSE) > 0;
}
private static boolean isTiePianPost(int positionType) {
return (positionType & AdUnitConstants.POSITION_TYPE.TIEPIAN_POST) > 0;
}
public static boolean isAdSlotTypeOK(int adSlotType, int positionType) {
switch (adSlotType) {
case AdUnitConstants.POSITION_TYPE.KAIPING:
return isKaiPing(positionType);
case AdUnitConstants.POSITION_TYPE.TIEPIAN:
return isTiePian(positionType);
case AdUnitConstants.POSITION_TYPE.TIEPIAN_MIDDLE:
return isTiePianMiddle(positionType);
case AdUnitConstants.POSITION_TYPE.TIEPIAN_PAUSE:
return isTiePianPause(positionType);
case AdUnitConstants.POSITION_TYPE.TIEPIAN_POST:
return isTiePianPost(positionType);
default:
return false;
}
}
}
3.AdUnitIndex 进行索引的匹配
public Set<Long> match(Integer positionType) {
Set<Long> adUnitIds = new HashSet<>();
objectMap.forEach((k, v) -> {
if (AdUnitObject.isAdSlotTypeOK(positionType,
v.getPositionType())) {
adUnitIds.add(k);
}
});
return adUnitIds;
}
public List<AdUnitObject> fetch(Collection<Long> adUnitIds) {
if (CollectionUtils.isEmpty(adUnitIds)) {
return Collections.emptyList();
}
List<AdUnitObject> result = new ArrayList<>();
adUnitIds.forEach(u -> {
AdUnitObject object = get(u);
if (object == null) {
log.error("AdUnitObject not found: {}", u);
return;
}
result.add(object);
});
return result;
}
4.预筛选功能实现,search服务的实现
package com.imooc.ad.search.impl;
import com.imooc.ad.index.DataTable;
import com.imooc.ad.index.adunit.AdUnitIndex;
import com.imooc.ad.search.ISearch;
import com.imooc.ad.search.vo.SearchRequest;
import com.imooc.ad.search.vo.SearchResponse;
import com.imooc.ad.search.vo.feature.DistrictFeature;
import com.imooc.ad.search.vo.feature.FeatureRelation;
import com.imooc.ad.search.vo.feature.ItFeature;
import com.imooc.ad.search.vo.feature.KeywordFeature;
import com.imooc.ad.search.vo.media.AdSlot;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Slf4j
@Service
public class SearchImpl implements ISearch {
@Override
public SearchResponse fetchAds(SearchRequest request) {
// 请求的广告位信息
List<AdSlot> adSlots = request.getRequestInfo().getAdSlots();
// 三个 Feature
KeywordFeature keywordFeature = request.getFeatureInfo().getKeywordFeature();
DistrictFeature districtFeature = request.getFeatureInfo().getDistrictFeature();
ItFeature itFeature = request.getFeatureInfo().getItFeature();
FeatureRelation relation = request.getFeatureInfo().getRelation();
// 构造响应对象
SearchResponse response = new SearchResponse();
Map<String, List<SearchResponse.Creative>> adSlot2Ads = response.getAdSlot2Ads();
for (AdSlot adSlot : adSlots) {
Set<Long> targetUnitIdSet;
// 根据流量类型获取初始 AdUnit
Set<Long> adUnitIdSet = DataTable.of(
AdUnitIndex.class
).match(adSlot.getPositionType());
}
return null;
}
}