[Spring cloud 광고 시스템 구현] 18. 광고 창의 검색

세 차원 에 따라 계속 여과 하 다.
지난 절 에서 우 리 는 데이터 정보 에 따라 걸 러 내 는 코드 를 실 현 했 지만 우리 의 조건 은 여러 조건 으로 우리 에 게 전 달 된 검색 서비스 일 수 있다. 본 절 에서 우 리 는 홍보 단원 의 세 가지 차원 조건 에 따라 걸 러 내 는 것 을 계속 실현 했다.
  • SearchImpl 클래스 에 여과 방법 추가
  • public class SearchImpl implements ISearch {
        @Override
        public SearchResponse fetchAds(SearchRequest request) {
            ...
                //         
                if (featureRelation == FeatureRelation.AND) {
                    filterKeywordFeature(adUnitIdSet, keywordFeature);
                    filterHobbyFeature(adUnitIdSet, hobbyFeatrue);
                    filterDistrictFeature(adUnitIdSet, districtFeature);
    
                    targetUnitIdSet = adUnitIdSet;
                } else {
                    getOrRelationUnitIds(adUnitIdSet, keywordFeature, hobbyFeatrue, districtFeature);
                }
            }
            return null;
        }
  • 세 가지 방법 을 정의 하여 여과
  • /**
         *               id
         */
        private Set getOrRelationUnitIds(Set adUnitIdsSet,
                                               KeywordFeature keywordFeature,
                                               HobbyFeatrue hobbyFeatrue,
                                               DistrictFeature districtFeature) {
            if (CollectionUtils.isEmpty(adUnitIdsSet)) return Collections.EMPTY_SET;
    
            //         ,         ,                ?
            Set keywordUnitIdSet = new HashSet<>(adUnitIdsSet);
            Set hobbyUnitIdSet = new HashSet<>(adUnitIdsSet);
            Set districtUnitIdSet = new HashSet<>(adUnitIdsSet);
    
            filterKeywordFeature(keywordUnitIdSet, keywordFeature);
            filterHobbyFeature(hobbyUnitIdSet, hobbyFeatrue);
            filterDistrictFeature(districtUnitIdSet, districtFeature);
    
            //        
            return new HashSet<>(
                    CollectionUtils.union(
                            CollectionUtils.union(keywordUnitIdSet, hobbyUnitIdSet),
                            districtUnitIdSet
                    )
            );
        }
    
        /**
         *           
         */
        private void filterKeywordFeature(Collection adUnitIds, KeywordFeature keywordFeature) {
            if (CollectionUtils.isEmpty(adUnitIds)) return;
            if (CollectionUtils.isNotEmpty(keywordFeature.getKeywords())) {
                //             ,              
                CollectionUtils.filter(
                        adUnitIds,
                        adUnitId -> IndexDataTableUtils.of(UnitKeywordIndexAwareImpl.class)
                                                       .match(adUnitId, keywordFeature.getKeywords())
                );
            }
        }
    
        /**
         *            
         */
        private void filterHobbyFeature(Collection adUnitIds, HobbyFeatrue hobbyFeatrue) {
            if (CollectionUtils.isEmpty(adUnitIds)) return;
            //            ,              
            if (CollectionUtils.isNotEmpty(hobbyFeatrue.getHobbys())) {
                CollectionUtils.filter(
                        adUnitIds,
                        adUnitId -> IndexDataTableUtils.of(UnitHobbyIndexAwareImpl.class)
                                                       .match(adUnitId, hobbyFeatrue.getHobbys())
                );
            }
        }
    
        /**
         *            
         */
        private void filterDistrictFeature(Collection adUnitIds, DistrictFeature districtFeature) {
            if (CollectionUtils.isEmpty(adUnitIds)) return;
            //              ,              
            if (CollectionUtils.isNotEmpty(districtFeature.getProvinceAndCities())) {
                CollectionUtils.filter(
                        adUnitIds,
                        adUnitId -> {
                            return IndexDataTableUtils.of(UnitDistrictIndexAwareImpl.class)
                                                      .match(adUnitId, districtFeature.getProvinceAndCities());
                        }
                );
            }
        }

    프로 모 션 유닛 id 에 따라 프로 모 션 아 이 디 어 를 얻 습 니 다.
    우 리 는 홍보 단원 과 홍보 창의 의 관계 가 얼마나 많은 지 알 고 있다. 앞에서 우 리 는 홍보 단원 ids 를 조회 했다. 그 다음 에 우 리 는 홍보 단원 id 에 따라 홍보 창의 코드, let 's code 를 얻 었 다. 먼저, 우 리 는 com.sxzhongf.ad.index.creative_relation_unit.CreativeRelationUnitIndexAwareImpl 관련 색인 에서 창의 적 인 ids 를 확대 하 는 것 을 찾 아야 한다.
     /**
         *       id      id
         */
        public List selectAdCreativeIds(List unitIndexObjects) {
            if (CollectionUtils.isEmpty(unitIndexObjects)) return Collections.emptyList();
    
            //          ids
            List result = new ArrayList<>();
            for (AdUnitIndexObject unitIndexObject : unitIndexObjects) {
                //      id      
                Set adCreativeIds = unitRelationCreativeMap.get(unitIndexObject.getUnitId());
                if (CollectionUtils.isNotEmpty(adCreativeIds)) result.addAll(adCreativeIds);
            }
    
            return result;
        }

    그리고 아 이 디 어 를 홍보 하 는 id list 를 얻 은 후에 우 리 는 창의 색인 실현 류 com.sxzhongf.ad.index.creative.CreativeIndexAwareImpl 에서 ids 에 따라 아 이 디 어 를 조회 하 는 방법 을 정의 했다.
    /**
     *   ids    list
     */
    public List findAllByIds(Collection ids) {
        if (CollectionUtils.isEmpty(ids)) return Collections.emptyList();
        List result = new ArrayList<>();
    
        for (Long id : ids) {
            CreativeIndexObject object = get(id);
            if (null != object)
                result.add(object);
        }
    
        return result;
    }

    이로부터 우 리 는 원 하 는 홍보 유닛 과 홍보 아 이 디 어 를 얻 었 습 니 다. 홍보 유닛 은 홍보 계획 을 포함 하기 때문에 우리 가 원 하 는 데 이 터 는 모두 얻 을 수 있 습 니 다. 그 다음 에 우 리 는 현재 우리 가 조회 한 데이터 의 상 태 를 걸 러 야 합 니 다. 어떤 데 이 터 는 우리 가 논리 적 으로 삭 제 했 을 수도 있 습 니 다.따라서 얻 은 데이터 가 효과 가 있 는 지 판단 해 야 한다.SearchImpl 류 에서 이 루어 집 니 다.
      /**
       *           
       */
      private void filterAdUnitAndPlanStatus(List unitIndexObjects, CommonStatus status) {
          if (CollectionUtils.isEmpty(unitIndexObjects)) return;
    
          //                
          CollectionUtils.filter(
                  unitIndexObjects,
                  unitIndexObject -> unitIndexObject.getUnitStatus().equals(status.getStatus()) &&
                          unitIndexObject.getAdPlanIndexObject().getPlanStatus().equals(status.getStatus())
          );
      }
    SearchImpl 에서 우 리 는 광고 창의 적 인 조 회 를 실현 한다.
    ...
    
    //          list
    List unitIndexObjects = IndexDataTableUtils.of(AdUnitIndexAwareImpl.class).fetch(adUnitIdSet);
    //        
    filterAdUnitAndPlanStatus(unitIndexObjects, CommonStatus.VALID);
    //        id list
    List creativeIds = IndexDataTableUtils.of(CreativeRelationUnitIndexAwareImpl.class)
                                                .selectAdCreativeIds(unitIndexObjects);
    //       ids      
    List creativeIndexObjects = IndexDataTableUtils.of(CreativeIndexAwareImpl.class)
    ...
    

    광고 위치 adslot 에 따라 창의 데이터 에 대한 여과 실현
    우리 의 광고 위 치 는 서로 다른 크기, 유형 이 있 기 때문에 우 리 는 우리 의 조회 차원 과 데이터 유형 에 부합 되 는 모든 조건 을 얻 은 후에 서로 다른 광고 위 치 를 대상 으로 서로 다른 광고 창의 정 보 를 보 여 줘 야 한다.
    /**
    *                       
    *
    * @param creativeIndexObjects       
    * @param width                   width
    * @param height                  height
    */
    private void filterCreativeByAdSlot(List creativeIndexObjects,
                                      Integer width,
                                      Integer height,
                                      List type) {
      if (CollectionUtils.isEmpty(creativeIndexObjects)) return;
    
      CollectionUtils.filter(
              creativeIndexObjects,
              creative -> {
                  //         
                  return creative.getAuditStatus().equals(CommonStatus.VALID.getStatus())
                          && creative.getWidth().equals(width)
                          && creative.getHeight().equals(height)
                          && type.contains(creative.getType());
              }
      );
    }
  • 검색 반환 대상 의 정상 적 인 업무 장면 을 구성 할 때 같은 광고 위 치 는 여러 개의 광고 정 보 를 보 여줄 수 있 고 하나의 광고 정보 만 보 여줄 수 있다. 이 는 구체 적 인 업무 장면 에 따라 서로 다른 처 리 를 해 야 한다. 이번 에는 시연 의 편 의 를 위해 돌아 오 는 창의 목록 에서 창의 적 인 광고 정 보 를 무 작위 로 선택 하여 보 여 준다.물론 여러분 도 업무 유형 에 따라 서로 다른 우선 순위 나 가중치 를 설정 하여 광고 선택 을 할 수 있 습 니 다.
  • /**
     *                     
     *
     * @param creativeIndexObjects     list
     */
    private List buildCreativeResponse(List creativeIndexObjects) {
        if (CollectionUtils.isEmpty(creativeIndexObjects)) return Collections.EMPTY_LIST;
    
        //          ,          ,          ,      
        CreativeIndexObject randomObject = creativeIndexObjects.get(
                Math.abs(new Random().nextInt()) % creativeIndexObjects.size()
        );
        //List result = new ArrayList<>();
        //result.add(SearchResponse.convert(randomObject));
    
        return Collections.singletonList(
                SearchResponse.convert(randomObject)
        );
    }

    완전한 요청 필터 구현 방법:
    @Service
    @Slf4j
    public class SearchImpl implements ISearch {
        @Override
        public SearchResponse fetchAds(SearchRequest request) {
    
            //         
            List adSlotList = request.getRequestInfo().getAdSlots();
    
            //    Feature  
            KeywordFeature keywordFeature = request.getFeatureInfo().getKeywordFeature();
            HobbyFeatrue hobbyFeatrue = request.getFeatureInfo().getHobbyFeatrue();
            DistrictFeature districtFeature = request.getFeatureInfo().getDistrictFeature();
            //Feature  
            FeatureRelation featureRelation = request.getFeatureInfo().getRelation();
    
    
            //      
            SearchResponse response = new SearchResponse();
            Map> adSlotRelationAds = response.getAdSlotRelationAds();
    
            for (AdSlot adSlot : 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);
    
                //        id list
                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)
                );
            }
    
            return response;
        }
        ...

    검색 서비스 대외 제공
  • 노출 API 인터페이스 에서 우 리 는 검색 서비스의 핵심 논 리 를 실현 했다. 그 다음 에 우 리 는 우리 의 광고 검색 서비스 인 터 페 이 스 를 대외 적 으로 노출 시 켜 야 한다. SearchController 에서 제공 해 야 한다.
        @PostMapping("/fetchAd")
        public SearchResponse fetchAdCreative(@RequestBody SearchRequest request) {
            log.info("ad-serach: fetchAd ->{}", JSON.toJSONString(request));
            return search.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          ,             
  • 좋은 웹페이지 즐겨찾기