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
}