func()

in filter/group_weight_count_filter.go [119:277]


func (f *GroupWeightCountFilter) doFilter(filterData *FilterData) error {
	start := time.Now()
	ctx := filterData.Context
	items := filterData.Data.([]*module.Item)
	if len(items) <= f.retainNum {
		return nil
	}

	var groupWeightStrategy GroupWeightStrategy
	switch f.groupWeightStrategy {
	case "avg":
		groupWeightStrategy = &AvgGroupWeightStrategy{scoreWeight: f.scoreWeight,
			groupMinNum: f.groupMinNum, groupMaxNum: f.groupMaxNum}
	default:
		groupWeightStrategy = &SoftmaxGroupWeightStrategy{scoreWeight: f.scoreWeight,
			groupMinNum: f.groupMinNum, groupMaxNum: f.groupMaxNum}
	}

	if len(f.groupWeightDimensionLimit) > 0 {
		items = f.groupWeightDimensionFilter(items, ctx)
	}

	newItems := make([]*module.Item, 0, f.retainNum)
	groupDimensionMap := make(map[string][]*module.Item)
	retainGroupDimensionMap := make(map[string][]*module.Item)
	dimensionScoreMap := make(map[string]float64)
	exceedNumDimensionMap := make(map[string]bool)

	for _, item := range items {
		val := item.StringProperty(f.dimension)
		if val == "" {
			val = "DEFAULT"
		}

		groupDimensionMap[val] = append(groupDimensionMap[val], item)
		dimensionScoreMap[val] += item.Score
	}

	if ctx.Debug {
		for dimension, itemList := range groupDimensionMap {
			log.Info(fmt.Sprintf("requestId=%s\tdimension=%s\tcount=%d", ctx.RecommendId, dimension, len(itemList)))
		}

		log.Info(fmt.Sprintf("requestId=%s\tevent=befor GroupWeightCountFilter", ctx.RecommendId))
	}

	var (
		retainNum = 0
	)

	groupWeightStrategy.SetDimensionScoreMap(dimensionScoreMap)
	groupWeightStrategy.TotalScore()
	for dimension := range groupDimensionMap {
		_, exceed := groupWeightStrategy.DimensionCount(dimension, f.retainNum)
		if exceed {
			exceedNumDimensionMap[dimension] = true
		}
	}
	// find exceed num dimension first
	if len(exceedNumDimensionMap) > 0 {
		for dimension, itemList := range groupDimensionMap {
			if _, ok := exceedNumDimensionMap[dimension]; ok {
				delete(dimensionScoreMap, dimension)
				count := f.groupMaxNum
				if len(itemList) <= count {
					retainGroupDimensionMap[dimension] = append(retainGroupDimensionMap[dimension], itemList...)
					groupDimensionMap[dimension] = groupDimensionMap[dimension][:0]
				} else {
					retainGroupDimensionMap[dimension] = append(retainGroupDimensionMap[dimension], itemList[:count]...)
					groupDimensionMap[dimension] = groupDimensionMap[dimension][count:]
				}

				retainNum += len(retainGroupDimensionMap[dimension])
			}
		}
	} else {
		for dimension, itemList := range groupDimensionMap {
			count, _ := groupWeightStrategy.DimensionCount(dimension, f.retainNum)

			if len(itemList) <= count {
				retainGroupDimensionMap[dimension] = append(retainGroupDimensionMap[dimension], itemList...)
				groupDimensionMap[dimension] = groupDimensionMap[dimension][:0]
			} else {
				retainGroupDimensionMap[dimension] = append(retainGroupDimensionMap[dimension], itemList[:count]...)
				groupDimensionMap[dimension] = groupDimensionMap[dimension][count:]
			}

			retainNum += len(retainGroupDimensionMap[dimension])
		}

	}

	if retainNum < f.retainNum && len(exceedNumDimensionMap) > 0 {
		num := f.retainNum - len(exceedNumDimensionMap)*f.groupMaxNum
		groupWeightStrategy.SetDimensionScoreMap(dimensionScoreMap)
		groupWeightStrategy.TotalScore()
		for dimension, itemList := range groupDimensionMap {
			if _, ok := exceedNumDimensionMap[dimension]; ok {
				continue
			}
			count, _ := groupWeightStrategy.DimensionCount(dimension, num)

			if len(itemList) <= count {
				retainGroupDimensionMap[dimension] = append(retainGroupDimensionMap[dimension], itemList...)
				groupDimensionMap[dimension] = groupDimensionMap[dimension][:0]
			} else {
				retainGroupDimensionMap[dimension] = append(retainGroupDimensionMap[dimension], itemList[:count]...)
				groupDimensionMap[dimension] = groupDimensionMap[dimension][count:]
			}

			retainNum += len(retainGroupDimensionMap[dimension])
		}
	}

	if retainNum > f.retainNum {
		for {
			for dimension, itemList := range retainGroupDimensionMap {
				if len(itemList) > f.groupMinNum {
					retainGroupDimensionMap[dimension] = itemList[:len(itemList)-1]
					retainNum--
					if retainNum == f.retainNum {
						break
					}
				}
			}

			if retainNum == f.retainNum {
				break
			}
		}
	} else if retainNum < f.retainNum {
		for {
			for dimension, itemList := range groupDimensionMap {
				if len(itemList) > 0 {
					retainGroupDimensionMap[dimension] = append(retainGroupDimensionMap[dimension], itemList[0])
					groupDimensionMap[dimension] = itemList[1:]
					retainNum++
				}
				if retainNum == f.retainNum {
					break
				}
			}
			if retainNum == f.retainNum {
				break
			}
		}
	}

	for dimension, itemList := range retainGroupDimensionMap {
		if ctx.Debug {
			log.Info(fmt.Sprintf("requestId=%s\tdimension=%s\tcount=%d", ctx.RecommendId, dimension, len(itemList)))
		}
		newItems = append(newItems, itemList...)
	}

	filterData.Data = newItems
	filterInfoLog(filterData, "GroupWeightCountFilter", f.name, len(newItems), start)
	return nil
}