门店评分-优化数据读取速度

This commit is contained in:
Rosy-zhudan
2019-09-12 15:36:39 +08:00
parent 86d35d58c5
commit 6b3b0bcd35
3 changed files with 139 additions and 97 deletions

View File

@@ -19,7 +19,7 @@ import (
const ( const (
EnableScheduleScoreStore = !true EnableScheduleScoreStore = !true
ParallelCount = 10 ParallelCount = 5
GoldMedalScore = 90 GoldMedalScore = 90
SilverMedalScore = 80 SilverMedalScore = 80
@@ -71,13 +71,11 @@ var (
) )
type AllStoreSkusWrapper struct { type AllStoreSkusWrapper struct {
//allStoreSkus map[int]map[int]*cms.StoreSkuNameExt
allStoreSkus map[int]map[int]int allStoreSkus map[int]map[int]int
locker sync.RWMutex locker sync.RWMutex
} }
func (a *AllStoreSkusWrapper) InitData() { func (a *AllStoreSkusWrapper) InitData() {
// a.allStoreSkus = make(map[int]map[int]*cms.StoreSkuNameExt)
a.allStoreSkus = make(map[int]map[int]int) a.allStoreSkus = make(map[int]map[int]int)
} }
@@ -85,17 +83,6 @@ func (a *AllStoreSkusWrapper) ClearData() {
a.allStoreSkus = nil a.allStoreSkus = nil
} }
// func (a *AllStoreSkusWrapper) SetData(storeID int, skuMapData map[int]*cms.StoreSkuNameExt) {
// a.locker.Lock()
// defer a.locker.Unlock()
// a.allStoreSkus[storeID] = skuMapData
// }
// func (a *AllStoreSkusWrapper) GetData(storeID int) map[int]*cms.StoreSkuNameExt {
// a.locker.RLock()
// defer a.locker.RUnlock()
// return a.allStoreSkus[storeID]
// }
func (a *AllStoreSkusWrapper) SetData(storeID int, skuMapData map[int]int) { func (a *AllStoreSkusWrapper) SetData(storeID int, skuMapData map[int]int) {
a.locker.Lock() a.locker.Lock()
defer a.locker.Unlock() defer a.locker.Unlock()
@@ -109,12 +96,28 @@ func (a *AllStoreSkusWrapper) GetData(storeID int) map[int]int {
} }
type StoreScoreDataWrapper struct { type StoreScoreDataWrapper struct {
storeScoreData map[int]*model.StoreScore storeScoreData map[int]*model.StoreScore
locker sync.RWMutex dailyBadCommentOrderCount map[int]int
dailyUnFinishOrderCount map[int]int
dailyFinishOrderCount map[int]int
dailyAbsentGoodsOrderCount map[int]int
locker sync.RWMutex
} }
func (s *StoreScoreDataWrapper) InitData() { func (s *StoreScoreDataWrapper) InitData() {
s.storeScoreData = make(map[int]*model.StoreScore) s.storeScoreData = make(map[int]*model.StoreScore)
s.dailyBadCommentOrderCount = make(map[int]int)
s.dailyUnFinishOrderCount = make(map[int]int)
s.dailyFinishOrderCount = make(map[int]int)
s.dailyAbsentGoodsOrderCount = make(map[int]int)
}
func (s *StoreScoreDataWrapper) ClearData() {
s.storeScoreData = nil
s.dailyBadCommentOrderCount = nil
s.dailyUnFinishOrderCount = nil
s.dailyFinishOrderCount = nil
s.dailyAbsentGoodsOrderCount = nil
} }
func (s *StoreScoreDataWrapper) SetData(storeID int, valueName string, value int) { func (s *StoreScoreDataWrapper) SetData(storeID int, valueName string, value int) {
@@ -130,6 +133,78 @@ func (s *StoreScoreDataWrapper) SetData(storeID int, valueName string, value int
valueInfo.FieldByName(valueName).SetInt(int64(value)) valueInfo.FieldByName(valueName).SetInt(int64(value))
} }
func (s *StoreScoreDataWrapper) SetDailyBadCommentOrderCount(storeCountList []*model.StoreCount) {
s.locker.Lock()
defer s.locker.Unlock()
for _, value := range storeCountList {
s.dailyBadCommentOrderCount[value.StoreID] = value.Count
}
}
func (s *StoreScoreDataWrapper) GetDailyBadCommentOrderCount(storeID int) int {
s.locker.RLock()
defer s.locker.RUnlock()
if count, ok := s.dailyBadCommentOrderCount[storeID]; ok {
return count
}
return 0
}
func (s *StoreScoreDataWrapper) SetDailyUnFinishOrderCount(storeCountList []*model.StoreCount) {
for _, value := range storeCountList {
s.dailyUnFinishOrderCount[value.StoreID] = value.Count
}
}
func (s *StoreScoreDataWrapper) GetDailyUnFinishOrderCount(storeID int) int {
s.locker.RLock()
defer s.locker.RUnlock()
if count, ok := s.dailyUnFinishOrderCount[storeID]; ok {
return count
}
return 0
}
func (s *StoreScoreDataWrapper) SetDailyFinishOrderCount(storeCountList []*model.StoreCount) {
for _, value := range storeCountList {
s.dailyFinishOrderCount[value.StoreID] = value.Count
}
}
func (s *StoreScoreDataWrapper) GetDailyFinishOrderCount(storeID int) int {
s.locker.RLock()
defer s.locker.RUnlock()
if count, ok := s.dailyFinishOrderCount[storeID]; ok {
return count
}
return 0
}
func (s *StoreScoreDataWrapper) SetDailyAbsentGoodsOrderCount(storeCountList []*model.StoreCount) {
for _, value := range storeCountList {
s.dailyAbsentGoodsOrderCount[value.StoreID] = value.Count
}
}
func (s *StoreScoreDataWrapper) GetDailyAbsentGoodsOrderCount(storeID int) int {
s.locker.RLock()
defer s.locker.RUnlock()
if count, ok := s.dailyAbsentGoodsOrderCount[storeID]; ok {
return count
}
return 0
}
func (s *StoreScoreDataWrapper) InsertStoreScore() {
for _, value := range s.storeScoreData {
dao.InsertStoreScore(value)
}
}
//得到所有门店的可售商品(优化内存,只存商品的价格) //得到所有门店的可售商品(优化内存,只存商品的价格)
func GetAllStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeList []*cms.StoreExt) { func GetAllStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeList []*cms.StoreExt) {
allStoreSkusWrapper.InitData() allStoreSkusWrapper.InitData()
@@ -137,13 +212,11 @@ func GetAllStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeList
storeInfo := batchItemList[0].(*cms.StoreExt) storeInfo := batchItemList[0].(*cms.StoreExt)
storeID := storeInfo.ID storeID := storeInfo.ID
jxSkuInfoData, _ := cms.GetStoreSkus(ctx, storeID, []int{}, true, "", true, map[string]interface{}{}, 0, -1) jxSkuInfoData, _ := cms.GetStoreSkus(ctx, storeID, []int{}, true, "", true, map[string]interface{}{}, 0, -1)
//jxSkuMapData := make(map[int]*cms.StoreSkuNameExt)
jxSkuPriceMapData := make(map[int]int) jxSkuPriceMapData := make(map[int]int)
for _, value := range jxSkuInfoData.SkuNames { for _, value := range jxSkuInfoData.SkuNames {
for _, skuInfo := range value.Skus2 { for _, skuInfo := range value.Skus2 {
saleStatus := jxutils.MergeSkuStatus(skuInfo.SkuStatus, skuInfo.StoreSkuStatus) saleStatus := jxutils.MergeSkuStatus(skuInfo.SkuStatus, skuInfo.StoreSkuStatus)
if saleStatus == model.SkuStatusNormal { if saleStatus == model.SkuStatusNormal {
//jxSkuMapData[skuInfo.SkuID] = value
jxSkuPriceMapData[skuInfo.SkuID] = skuInfo.BindPrice jxSkuPriceMapData[skuInfo.SkuID] = skuInfo.BindPrice
} }
} }
@@ -151,7 +224,7 @@ func GetAllStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeList
allStoreSkusWrapper.SetData(storeID, jxSkuPriceMapData) allStoreSkusWrapper.SetData(storeID, jxSkuPriceMapData)
return retVal, err return retVal, err
} }
taskParallel := tasksch.NewParallelTask("得到所有门店商品", nil, ctx, taskFunc, storeList) taskParallel := tasksch.NewParallelTask("得到所有门店商品", tasksch.NewParallelConfig().SetParallelCount(ParallelCount), ctx, taskFunc, storeList)
tasksch.HandleTask(taskParallel, parentTask, true).Run() tasksch.HandleTask(taskParallel, parentTask, true).Run()
taskParallel.GetResult(0) taskParallel.GetResult(0)
} }
@@ -251,15 +324,10 @@ func ScoreAveragePickupTime(storeInfo *cms.StoreExt) {
} }
//差评订单和完成订单比例小于0.2%,得满分10分每增加0.1%减1分 //差评订单和完成订单比例小于0.2%,得满分10分每增加0.1%减1分
func ScoreBadCommentOrder(storeInfo *cms.StoreExt, paramFinishOrderCount int64) (finishOrderCount int64) { func ScoreBadCommentOrder(storeInfo *cms.StoreExt) {
storeID := storeInfo.ID storeID := storeInfo.ID
db := dao.GetDB() badCommentOrderCount := storeScoreDataWrapper.GetDailyBadCommentOrderCount(storeID)
badCommentOrderCount, _ := dao.GetDailyBadCommentOrderCount(db, storeID) finishOrderCount := storeScoreDataWrapper.GetDailyFinishOrderCount(storeID)
if paramFinishOrderCount == -1 {
finishOrderCount, _ = dao.GetDailyFinishOrderCount(db, storeID)
} else {
finishOrderCount = paramFinishOrderCount
}
finalScore := 0 finalScore := 0
if finishOrderCount > 0 { if finishOrderCount > 0 {
badCommentOrderRatio := float64(badCommentOrderCount) * 100 / float64(finishOrderCount) badCommentOrderRatio := float64(badCommentOrderCount) * 100 / float64(finishOrderCount)
@@ -274,20 +342,13 @@ func ScoreBadCommentOrder(storeInfo *cms.StoreExt, paramFinishOrderCount int64)
} }
} }
storeScoreDataWrapper.SetData(storeID, model.FieldBadCommentOrder, finalScore) storeScoreDataWrapper.SetData(storeID, model.FieldBadCommentOrder, finalScore)
return finishOrderCount
} }
//未完成订单和完成订单比小于1%得满分10分比例每增加5%分数减1 //未完成订单和完成订单比小于1%得满分10分比例每增加5%分数减1
func ScoreUnfinishOrder(storeInfo *cms.StoreExt, paramFinishOrderCount int64) (finishOrderCount int64) { func ScoreUnfinishOrder(storeInfo *cms.StoreExt) {
storeID := storeInfo.ID storeID := storeInfo.ID
db := dao.GetDB() unFinishOrderCount := storeScoreDataWrapper.GetDailyUnFinishOrderCount(storeID)
unFinishOrderCount, _ := dao.GetDailyUnFinishOrderCount(db, storeID) finishOrderCount := storeScoreDataWrapper.GetDailyFinishOrderCount(storeID)
if paramFinishOrderCount == -1 {
finishOrderCount, _ = dao.GetDailyFinishOrderCount(db, storeID)
} else {
finishOrderCount = paramFinishOrderCount
}
finalScore := 0 finalScore := 0
if finishOrderCount > 0 { if finishOrderCount > 0 {
unfinishOrderRatio := float64(unFinishOrderCount) * 100 / float64(finishOrderCount) unfinishOrderRatio := float64(unFinishOrderCount) * 100 / float64(finishOrderCount)
@@ -302,20 +363,13 @@ func ScoreUnfinishOrder(storeInfo *cms.StoreExt, paramFinishOrderCount int64) (f
} }
} }
storeScoreDataWrapper.SetData(storeID, model.FieldUnfinishOrder, finalScore) storeScoreDataWrapper.SetData(storeID, model.FieldUnfinishOrder, finalScore)
return finishOrderCount
} }
//缺货订单和完成订单比小于1%得10分比例每增加0.1%减1分 //缺货订单和完成订单比小于1%得10分比例每增加0.1%减1分
func ScoreAbsentGoodsOrder(storeInfo *cms.StoreExt, paramFinishOrderCount int64) (finishOrderCount int64) { func ScoreAbsentGoodsOrder(storeInfo *cms.StoreExt) {
storeID := storeInfo.ID storeID := storeInfo.ID
db := dao.GetDB() absentGoodsOrderCount := storeScoreDataWrapper.GetDailyAbsentGoodsOrderCount(storeID)
absentGoodsOrderCount, _ := dao.GetDailyAbsentGoodsOrderCount(db, storeID) finishOrderCount := storeScoreDataWrapper.GetDailyFinishOrderCount(storeID)
if paramFinishOrderCount == -1 {
finishOrderCount, _ = dao.GetDailyFinishOrderCount(db, storeID)
} else {
finishOrderCount = paramFinishOrderCount
}
finalScore := 0 finalScore := 0
if finishOrderCount > 0 { if finishOrderCount > 0 {
absentGoodsOrderRatio := float64(absentGoodsOrderCount) * 100 / float64(finishOrderCount) absentGoodsOrderRatio := float64(absentGoodsOrderCount) * 100 / float64(finishOrderCount)
@@ -330,8 +384,6 @@ func ScoreAbsentGoodsOrder(storeInfo *cms.StoreExt, paramFinishOrderCount int64)
} }
} }
storeScoreDataWrapper.SetData(storeID, model.FieldAbsentGoodsOrder, finalScore) storeScoreDataWrapper.SetData(storeID, model.FieldAbsentGoodsOrder, finalScore)
return finishOrderCount
} }
//促销品数量20个以上为满分10分每少2个扣1分 //促销品数量20个以上为满分10分每少2个扣1分
@@ -447,12 +499,6 @@ func GetStoreSkusAveragePrice(storeList []*cms.StoreExt) map[int]int {
for _, storeInfo := range storeList { for _, storeInfo := range storeList {
storeID := storeInfo.ID storeID := storeInfo.ID
storeSkuMapData := allStoreSkusWrapper.GetData(storeID) storeSkuMapData := allStoreSkusWrapper.GetData(storeID)
// for _, value := range storeSkuMapData {
// skuID := value.Skus2[0].SkuID
// skuPrice := value.Skus2[0].BindPrice
// skusTotalPrice[skuID] += skuPrice
// skusCount[skuID]++
// }
for skuID, skuPrice := range storeSkuMapData { for skuID, skuPrice := range storeSkuMapData {
skusTotalPrice[skuID] += skuPrice skusTotalPrice[skuID] += skuPrice
skusCount[skuID]++ skusCount[skuID]++
@@ -466,14 +512,6 @@ func GetStoreSkusAveragePrice(storeList []*cms.StoreExt) map[int]int {
func GetSkusCountLessEqualAvgPrice(storeID int, skusAveragePrice map[int]int) (count int) { func GetSkusCountLessEqualAvgPrice(storeID int, skusAveragePrice map[int]int) (count int) {
storeSkuMapData := allStoreSkusWrapper.GetData(storeID) storeSkuMapData := allStoreSkusWrapper.GetData(storeID)
// for _, value := range storeSkuMapData {
// skuID := value.Skus2[0].SkuID
// skuPrice := value.Skus2[0].BindPrice
// skuAvgPrice := skusAveragePrice[skuID]
// if skuPrice <= skuAvgPrice {
// count++
// }
// }
for skuID, skuPrice := range storeSkuMapData { for skuID, skuPrice := range storeSkuMapData {
skuAvgPrice := skusAveragePrice[skuID] skuAvgPrice := skusAveragePrice[skuID]
if skuPrice <= skuAvgPrice { if skuPrice <= skuAvgPrice {
@@ -536,7 +574,7 @@ func GetFilterStoreListEx(storeList []*cms.StoreExt, storeIDMap map[int]int) (ou
func ScoreStore(ctx *jxcontext.Context, storeIDList []int) (retVal interface{}, err error) { func ScoreStore(ctx *jxcontext.Context, storeIDList []int) (retVal interface{}, err error) {
var storeList []*cms.StoreExt var storeList []*cms.StoreExt
taskCount := 4 taskCount := 5
taskSeqFunc := func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { taskSeqFunc := func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
switch step { switch step {
case 0: case 0:
@@ -551,6 +589,16 @@ func ScoreStore(ctx *jxcontext.Context, storeIDList []int) (retVal interface{},
GetAllStoreSkus(ctx, task, storeList) GetAllStoreSkus(ctx, task, storeList)
baseapi.SugarLogger.Debugf("ScoreStore step1 end") baseapi.SugarLogger.Debugf("ScoreStore step1 end")
case 2: case 2:
db := dao.GetDB()
storeCountList, _ := dao.GetDailyBadCommentOrderCount(db)
storeScoreDataWrapper.SetDailyBadCommentOrderCount(storeCountList)
storeCountList, _ = dao.GetDailyUnFinishOrderCount(db)
storeScoreDataWrapper.SetDailyUnFinishOrderCount(storeCountList)
storeCountList, _ = dao.GetDailyFinishOrderCount(db)
storeScoreDataWrapper.SetDailyFinishOrderCount(storeCountList)
storeCountList, _ = dao.GetDailyAbsentGoodsOrderCount(db)
storeScoreDataWrapper.SetDailyAbsentGoodsOrderCount(storeCountList)
case 3:
baseapi.SugarLogger.Debugf("ScoreStore step2 begin") baseapi.SugarLogger.Debugf("ScoreStore step2 begin")
taskFunc := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { taskFunc := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
storeInfo := batchItemList[0].(*cms.StoreExt) storeInfo := batchItemList[0].(*cms.StoreExt)
@@ -559,9 +607,9 @@ func ScoreStore(ctx *jxcontext.Context, storeIDList []int) (retVal interface{},
ScoreStoreOpenTime(storeInfo) ScoreStoreOpenTime(storeInfo)
ScoreSaleSkuCount(storeInfo) ScoreSaleSkuCount(storeInfo)
ScoreAveragePickupTime(storeInfo) ScoreAveragePickupTime(storeInfo)
finishOrderCount := ScoreBadCommentOrder(storeInfo, -1) ScoreBadCommentOrder(storeInfo)
ScoreUnfinishOrder(storeInfo, finishOrderCount) ScoreUnfinishOrder(storeInfo)
ScoreAbsentGoodsOrder(storeInfo, finishOrderCount) ScoreAbsentGoodsOrder(storeInfo)
ScorePromotionSku(storeInfo) ScorePromotionSku(storeInfo)
ScoreFullVendor(storeInfo) ScoreFullVendor(storeInfo)
ScoreStoreRange(storeInfo) ScoreStoreRange(storeInfo)
@@ -577,9 +625,10 @@ func ScoreStore(ctx *jxcontext.Context, storeIDList []int) (retVal interface{},
baseapi.SugarLogger.Debugf("ScoreStore taskParallel error:%v", err) baseapi.SugarLogger.Debugf("ScoreStore taskParallel error:%v", err)
} }
baseapi.SugarLogger.Debugf("ScoreStore step2 end") baseapi.SugarLogger.Debugf("ScoreStore step2 end")
case 3: case 4:
baseapi.SugarLogger.Debugf("ScoreStore step3 begin") baseapi.SugarLogger.Debugf("ScoreStore step3 begin")
InsertStoreScore() storeScoreDataWrapper.InsertStoreScore()
storeScoreDataWrapper.ClearData()
allStoreSkusWrapper.ClearData() allStoreSkusWrapper.ClearData()
baseapi.SugarLogger.Debugf("ScoreStore step3 end") baseapi.SugarLogger.Debugf("ScoreStore step3 end")
} }
@@ -591,12 +640,6 @@ func ScoreStore(ctx *jxcontext.Context, storeIDList []int) (retVal interface{},
return retVal, err return retVal, err
} }
func InsertStoreScore() {
for _, value := range storeScoreDataWrapper.storeScoreData {
dao.InsertStoreScore(value)
}
}
func ScheduleScoreStore() { func ScheduleScoreStore() {
if EnableScheduleScoreStore { if EnableScheduleScoreStore {
ScheduleTimerFunc("ScheduleScoreStore", func() { ScheduleTimerFunc("ScheduleScoreStore", func() {

View File

@@ -306,42 +306,36 @@ func GetDailyFinishOrderList(db *DaoDB, storeID int) (orderList []*model.OrderPi
return orderList, GetRows(db, &orderList, sql, sqlParams...) return orderList, GetRows(db, &orderList, sql, sqlParams...)
} }
func GetDailyBadCommentOrderCount(db *DaoDB, storeID int) (count int64, err error) { func GetDailyBadCommentOrderCount(db *DaoDB) (storeCountList []*model.StoreCount, err error) {
sql := `select count(*) from jx_bad_comments where DATE(createtime) = CURDATE() and jxstoreid = ?` sql := `select jxstoreid store_id, COUNT(*) count from jx_bad_comments where DATE(createtime) = CURDATE() GROUP BY jxstoreid`
sqlParams := []interface{}{ err = GetRows(db, &storeCountList, sql)
storeID,
}
err = GetRow(db, &count, sql, sqlParams...)
return count, err return storeCountList, err
} }
func GetDailyUnFinishOrderCount(db *DaoDB, storeID int) (num int64, err error) { func GetDailyUnFinishOrderCount(db *DaoDB) (storeCountList []*model.StoreCount, err error) {
return GetDailyEndOrderCount(db, storeID, []int{model.OrderStatusCanceled}, false) return GetDailyEndOrderCount(db, []int{model.OrderStatusCanceled}, false)
} }
func GetDailyFinishOrderCount(db *DaoDB, storeID int) (num int64, err error) { func GetDailyFinishOrderCount(db *DaoDB) (storeCountList []*model.StoreCount, err error) {
return GetDailyEndOrderCount(db, storeID, []int{model.OrderStatusFinished}, false) return GetDailyEndOrderCount(db, []int{model.OrderStatusFinished}, false)
} }
func GetDailyAbsentGoodsOrderCount(db *DaoDB, storeID int) (num int64, err error) { func GetDailyAbsentGoodsOrderCount(db *DaoDB) (storeCountList []*model.StoreCount, err error) {
return GetDailyEndOrderCount(db, storeID, []int{model.OrderStatusFinished, model.OrderStatusCanceled}, true) return GetDailyEndOrderCount(db, []int{model.OrderStatusFinished, model.OrderStatusCanceled}, true)
} }
func GetDailyEndOrderCount(db *DaoDB, storeID int, statusList []int, isAbsentOrder bool) (count int64, err error) { func GetDailyEndOrderCount(db *DaoDB, statusList []int, isAbsentOrder bool) (storeCountList []*model.StoreCount, err error) {
sql := `SELECT COUNT(*) FROM goods_order sql := `SELECT jx_store_id store_id, COUNT(*) count FROM goods_order
WHERE DATE(order_finished_at) = CURDATE() WHERE DATE(order_finished_at) = CURDATE()
AND jx_store_id = ?
AND status IN (` + GenQuestionMarks(len(statusList)) + `)` AND status IN (` + GenQuestionMarks(len(statusList)) + `)`
if isAbsentOrder { if isAbsentOrder {
sql += ` sql += `
AND adjust_count > 0` AND adjust_count > 0`
} }
sqlParams := []interface{}{ sql += `
storeID, GROUP BY jx_store_id`
} err = GetRow(db, &storeCountList, sql)
sqlParams = append(sqlParams, statusList)
err = GetRow(db, &count, sql, sqlParams...)
return count, err return storeCountList, err
} }

View File

@@ -47,3 +47,8 @@ type WeeklyStoreScore struct {
ItemTotalScore int `json:"itemTotalScore"` ItemTotalScore int `json:"itemTotalScore"`
Level int `json:"level"` Level int `json:"level"`
} }
type StoreCount struct {
StoreID int `orm:"column(store_id)"`
Count int
}