[Spring cloud implements ad system step by step] 17. Query ads based on traffic type

Posted by Hatdrawn on Mon, 12 Aug 2019 18:21:27 +0200

Advertising Retrieval Service

Functional introduction

Media (display ads opened by mobile APP, big screen ads seen on the road, etc.)

Request Data Object Implementation

From the image above, we can see that when the media makes a request to our advertising retrieval system, there are a lot of request parameter information in the request. They are divided into three parts. We encoding and encapsulating the object information of these parameters and the information of our request itself.Let's code.

  • Create ad retrieval request interface
/**
 * ISearch for Request interface,
 * Get advertising response information based on who requested it
 *
 * @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang | If initial </a>
 */
@FunctionalInterface
public interface ISearch {

    /**
     * Return ad results on request
     */
    SearchResponse fetchAds(SearchRequest request);
}
  • Create SearchRequest with three parts: mediaId,RequestInfo,FeatureInfo
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SearchRequest {

    //Media requests labeling
    private String mediaId;
    //Request basic information
    private RequestInfo requestInfo;
    //Matching information
    private FeatureInfo featureInfo;

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class RequestInfo {
        private String requestId;

        private List<AdSlot> adSlots;
        private App app;
        private Geo geo;
        private Device device;
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class FeatureInfo {

        private KeywordFeature keywordFeature;
        private DistrictFeature districtFeature;
        private HobbyFeatrue hobbyFeatrue;

        private FeatureRelation relation = FeatureRelation.AND;
    }
}

Everyone else can go github portal & gitee portal Download the source code.

Retrieving Response Object Definitions
/**
 * SearchResponse for Retrieving API Response Objects
 *
 * @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang | If initial </a>
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SearchResponse {

    //One advertising space to display multiple advertisements
    //Map key is AdSlot#adSlotCode
    public Map<String, List<Creative>> adSlotRelationAds = new HashMap<>();

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public static class Creative {

        private Long adId;
        private String adUrl;
        private Integer width;
        private Integer height;
        private Integer type;
        private Integer materialType;

        //Show monitoring url
        private List<String> showMonitorUrl = Arrays.asList("www.life-runner.com", "www.babydy.cn");
        //Click to monitor url
        private List<String> clickMonitorUrl = Arrays.asList("www.life-runner.com", "www.babydy.cn");
    }

    /**
     * Our retrieval service is for in-memory index retrieval, so we need a conversion method
     */
    public static Creative convert(CreativeIndexObject object) {

        return Creative.builder()
                       .adId(object.getAdId())
                       .adUrl(object.getAdUrl())
                       .width(object.getWidth())
                       .height(object.getHeight())
                       .type(object.getType())
                       .materialType(object.getMaterialType())
                       .build();
    }
}
Filter by traffic type

Traffic type itself belongs to the category under the promotion unit. There are many kinds of patch advertisements, open-screen advertisements and so on. These types need to be synchronized with the media. The media will launch different advertisement requests according to different traffic types. We need to define an information class of traffic type first.

public class AdUnitConstants {
    public static class PositionType{
        //Full-screen ad format displayed at the start of App with a short display time.
        private static final int KAIPING = 1;
        //Advertisements before the start of the movie
        private static final int TIEPIAN = 2;
        //Movie Play Midway Advertising
        private static final int TIEPIAN_MIDDLE = 4;
        //Advertisements played when video is paused
        private static final int TIEPIAN_PAUSE = 8;
        //Video finished playing
        private static final int TIEPIAN_POST = 16;
    }
}

From these types of numbers, we can see that they are multiples of 2, which is to improve performance using bit operations.

In com.sxzhongf.ad.index.adunit.AdUnitIndexObject, we add a type checking method:

public static boolean isAdSlotType(int adSlotType, int positionType) {
        switch (adSlotType) {
            case AdUnitConstants.PositionType.KAIPING:
                return isKaiPing(positionType);
            case AdUnitConstants.PositionType.TIEPIAN:
                return isTiePian(positionType);
            case AdUnitConstants.PositionType.TIEPIAN_MIDDLE:
                return isTiePianMiddle(positionType);
            case AdUnitConstants.PositionType.TIEPIAN_PAUSE:
                return isTiePianPause(positionType);
            case AdUnitConstants.PositionType.TIEPIAN_POST:
                return isTiePianPost(positionType);
            default:
                return false;
        }
    }

    /**
     * And operations, low bits, high bits, etc.
     * If > 0, it opens the screen
     */
    private static boolean isKaiPing(int positionType) {
        return (positionType & AdUnitConstants.PositionType.KAIPING) > 0;
    }
    private static boolean isTiePianMiddle(int positionType) {
        return (positionType & AdUnitConstants.PositionType.TIEPIAN_MIDDLE) > 0;
    }

    private static boolean isTiePianPause(int positionType) {
        return (positionType & AdUnitConstants.PositionType.TIEPIAN_PAUSE) > 0;
    }

    private static boolean isTiePianPost(int positionType) {
        return (positionType & AdUnitConstants.PositionType.TIEPIAN_POST) > 0;
    }

    private static boolean isTiePian(int positionType) {
        return (positionType & AdUnitConstants.PositionType.TIEPIAN) > 0;
    }

Anyway, we all need data query filtering based on positionType. We added two methods to the previous com.sxzhongf.ad.index.adunit.AdUnitIndexAwareImpl to achieve filtering:

/**
     * Filter for the presence of UnitIds that satisfy positionType
     */
    public Set<Long> match(Integer positionType) {
        Set<Long> adUnitIds = new HashSet<>();
        objectMap.forEach((k, v) -> {
            if (AdUnitIndexObject.isAdSlotType(positionType, v.getPositionType())) {
                adUnitIds.add(k);
            }
        });
        return adUnitIds;
    }

    /**
     * Query AdUnit list based on UnitIds
     */
    public List<AdUnitIndexObject> fetch(Collection<Long> adUnitIds) {
        if (CollectionUtils.isEmpty(adUnitIds)) {
            return Collections.EMPTY_LIST;
        }
        List<AdUnitIndexObject> result = new ArrayList<>();
        adUnitIds.forEach(id -> {
            AdUnitIndexObject object = get(id);
            if (null == object) {
                log.error("AdUnitIndexObject does not found:{}", id);
                return;
            }
            result.add(object);
        });

        return result;
    }
  • Implement Search Service Interface

Above all, we have prepared a series of query methods to query ad unit information according to the traffic type. Now we begin to implement our query interface, in which we can get the media's request object information with a series of filter parameters needed for query:

/**
 * SearchImpl for Implement search service
 *
 * @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang | If initial </a>
 */
@Service
@Slf4j
public class SearchImpl implements ISearch {
    @Override
    public SearchResponse fetchAds(SearchRequest request) {

        //Get Request Advertising Bit Information
        List<AdSlot> adSlotList = request.getRequestInfo().getAdSlots();

        //Get three Feature information
        KeywordFeature keywordFeature = request.getFeatureInfo().getKeywordFeature();
        HobbyFeatrue hobbyFeatrue = request.getFeatureInfo().getHobbyFeatrue();
        DistrictFeature districtFeature = request.getFeatureInfo().getDistrictFeature();
        //Feature Relationships
        FeatureRelation featureRelation = request.getFeatureInfo().getRelation();

        //Construct Response Object
        SearchResponse response = new SearchResponse();
        Map<String, List<SearchResponse.Creative>> adSlotRelationAds = response.getAdSlotRelationAds();

        for (AdSlot adSlot : adSlotList) {
            Set<Long> targetUnitIdSet;
            //Get initial advertising information from the cache based on traffic type
            Set<Long> adUnitIdSet = IndexDataTableUtils.of(
                    AdUnitIndexAwareImpl.class
            ).match(adSlot.getPositionType());
        }
        return null;
    }
}

Topics: Java Mobile encoding github