@@ -0,0 +1,44 @@
|
||||
package visitlogmod
|
||||
|
||||
import (
|
||||
"91porn-server/common/pageopt"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
type VisitLogSlice []VisitLog
|
||||
|
||||
func (v VisitLogSlice) ToUIDs() []uint64 {
|
||||
uids := make([]uint64, len(v))
|
||||
for i, l := range v {
|
||||
uids[i] = l.UID
|
||||
}
|
||||
return uids
|
||||
}
|
||||
|
||||
type Matcher = pageopt.Matcher
|
||||
|
||||
// CreatedAtGTEAndLTMatch
|
||||
type CreatedAtGTEAndLTMatch = pageopt.CreatedAtGTEAndLTMatch
|
||||
|
||||
func List(sort bson.D, skip, limit *int64, mats ...Matcher) (VisitLogSlice, error) {
|
||||
opt := (&options.FindOptions{})
|
||||
if len(sort) != 0 {
|
||||
opt.SetSort(sort)
|
||||
}
|
||||
if skip != nil {
|
||||
opt.SetSkip(*skip)
|
||||
}
|
||||
if limit != nil {
|
||||
opt.SetLimit(*limit)
|
||||
}
|
||||
filter := pageopt.MergeM(mats)
|
||||
list := VisitLogSlice{}
|
||||
return list, coll(nil).Find(&list, filter, opt)
|
||||
}
|
||||
|
||||
func Count(matchs ...pageopt.Matcher) (int64, error) {
|
||||
filter := pageopt.MergeM(matchs)
|
||||
return coll(nil).Count(filter)
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package visitlogmod
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"91porn-server/common/db"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
// 以天为单位,统计用户的首次访问的日志
|
||||
type VisitLog struct {
|
||||
ID *primitive.ObjectID `json:"id" bson:"_id,omitempty"` //记录Id
|
||||
SumDate time.Time `json:"sumDate" bson:"sumDate"` //每日零点
|
||||
UID uint64 `json:"uid" bson:"uid"` //用户ID
|
||||
IP string `json:"ip" bson:"ip"` //IP
|
||||
SysType string `json:"sysType" bson:"sysType"` //操作系统类型 安卓 IOS
|
||||
Ver string `json:"ver" bson:"ver"` //APP版本号
|
||||
DevType string `json:"devType" bson:"devType"` //设备型号
|
||||
DevID string `json:"devID" bson:"devID"` //设备ID
|
||||
BuildID string `json:"buildID" bson:"buildID"` //app构建ID(包ID)
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` //创建时间
|
||||
|
||||
IsDirect bool `json:"isDirect" bson:"isDirect"` // true:是直推用户
|
||||
DistrictCode string `json:"districtCode" bson:"districtCode"` // 渠道码
|
||||
RegisterTime time.Time `json:"registerTime" bson:"registerTime"` //用户注册时间
|
||||
IsDeduction bool `json:"isDeduction" bson:"isDeduction"` // true:CPA扣量用户
|
||||
}
|
||||
|
||||
type FilterDoc struct {
|
||||
SumDate time.Time `bson:"sumDate"` //每日零点
|
||||
UID uint64 `bson:"uid"` //用户ID
|
||||
}
|
||||
|
||||
func Init() {
|
||||
mdb = db.Init(table)
|
||||
initIndex()
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
package visitlogmod
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"91porn-server/common/db"
|
||||
"91porn-server/common/log"
|
||||
"91porn-server/common/pageopt"
|
||||
"91porn-server/models"
|
||||
"91porn-server/models/v/usermod"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
var mdb *db.MongoDB
|
||||
|
||||
const table = models.VisitLog
|
||||
|
||||
func coll(t *db.MongoTool) *db.MongoTool {
|
||||
if t == nil {
|
||||
return mdb.Coll(table)
|
||||
}
|
||||
return t.Coll(table)
|
||||
}
|
||||
|
||||
// InitIndex 设置index
|
||||
func initIndex() {
|
||||
many := []mongo.IndexModel{ //batch set indexes //value is the type 1 or -1
|
||||
{
|
||||
Keys: bson.D{{Key: "uid", Value: 1}},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{{Key: "sumDate", Value: -1}, {Key: "uid", Value: 1}},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{{Key: "createdAt", Value: -1}},
|
||||
},
|
||||
}
|
||||
if _, err := coll(nil).CreateIndex(many); err != nil {
|
||||
panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err))
|
||||
}
|
||||
}
|
||||
|
||||
func DataClean(deleteAt time.Time) (int64, error) {
|
||||
res, err := coll(nil).DeleteMany(bson.M{"createdAt": bson.M{"$lt": deleteAt}})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return res.DeletedCount, nil
|
||||
}
|
||||
|
||||
func UpsertUserVisit(l *VisitLog) (*mongo.UpdateResult, error) {
|
||||
l.CreatedAt = time.Now()
|
||||
b, _ := bson.Marshal(l)
|
||||
m := bson.M{}
|
||||
_ = bson.Unmarshal(b, &m)
|
||||
return coll(nil).UpsertOne(bson.M{"sumDate": l.SumDate, "uid": l.UID}, bson.M{"$setOnInsert": m})
|
||||
}
|
||||
|
||||
func UIDListByCreatedTime(start time.Time, end time.Time, mats ...Matcher) ([]uint64, error) {
|
||||
list := []struct {
|
||||
UID uint64 `bson:"uid"` //用户ID
|
||||
}{}
|
||||
mats = append(mats, (&CreatedAtGTEAndLTMatch{GTE: &start, LT: &end}).New())
|
||||
filter := pageopt.MergeM(mats)
|
||||
opt := (&options.FindOptions{}).SetProjection(bson.M{
|
||||
"uid": 1,
|
||||
})
|
||||
if err := coll(nil).Find(&list, filter, opt); err != nil {
|
||||
log.Error("UIDListByCreatedTime failed", log.Any("filter", filter), log.E(err))
|
||||
return nil, err
|
||||
}
|
||||
uids := make([]uint64, len(list))
|
||||
for i, v := range list {
|
||||
uids[i] = v.UID
|
||||
}
|
||||
return uids, nil
|
||||
}
|
||||
|
||||
func GetSumDateCountMap(uidList []uint64) (map[uint64]int64, error) {
|
||||
if len(uidList) == 0 {
|
||||
return make(map[uint64]int64), nil
|
||||
}
|
||||
pipeLine := []bson.M{
|
||||
{
|
||||
"$match": bson.M{
|
||||
"uid": bson.M{
|
||||
"$in": uidList,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"$group": bson.M{
|
||||
"_id": "$uid",
|
||||
"count": bson.M{
|
||||
"$sum": 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
list := make([]struct {
|
||||
UID uint64 `bson:"_id"`
|
||||
Count int64 `bson:"count"`
|
||||
}, 0, len(uidList))
|
||||
if err := coll(nil).Aggregate(&list, pipeLine); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
countMap := make(map[uint64]int64, len(list))
|
||||
for _, v := range list {
|
||||
countMap[v.UID] = v.Count
|
||||
}
|
||||
return countMap, nil
|
||||
}
|
||||
|
||||
// RetainUserListByTime 存留user
|
||||
func RetainUserListByTime(createUserStart, createUserEnd, visitStart, visitEnd time.Time, mats ...usermod.Matcher) ([]usermod.User, error) {
|
||||
visitFilter := (&CreatedAtGTEAndLTMatch{GTE: &visitStart, LT: &visitEnd}).New().Filter()
|
||||
visitList := make([]struct {
|
||||
UID uint64 `bson:"uid"`
|
||||
}, 0)
|
||||
visitOpt := (&options.FindOptions{}).SetProjection(bson.M{
|
||||
"uid": 1,
|
||||
})
|
||||
if err := coll(nil).Find(&visitList, visitFilter, visitOpt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
visitUIDList := make([]uint64, len(visitList))
|
||||
for i, v := range visitList {
|
||||
visitUIDList[i] = v.UID
|
||||
}
|
||||
return usermod.UserListByCreateTimeAndUIDS(createUserStart, createUserEnd, visitUIDList, mats...)
|
||||
}
|
||||
|
||||
// RetainUIDListByTime 存留UID
|
||||
func RetainUIDListByTime(createStart, createEnd, visitStart, visitEnd time.Time, mats ...usermod.Matcher) ([]uint64, error) {
|
||||
visitList := make([]struct {
|
||||
UID uint64 `bson:"uid"`
|
||||
}, 0)
|
||||
visitFilter := (&CreatedAtGTEAndLTMatch{GTE: &visitStart, LT: &visitEnd}).New().Filter()
|
||||
visitOpt := (&options.FindOptions{}).SetProjection(bson.M{
|
||||
"uid": 1,
|
||||
})
|
||||
if err := coll(nil).Find(&visitList, visitFilter, visitOpt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
visitUIDList := make([]uint64, len(visitList))
|
||||
for i, v := range visitList {
|
||||
visitUIDList[i] = v.UID
|
||||
}
|
||||
return usermod.UIDListByCreateTimeAndUIDS(createStart, createEnd, visitUIDList, mats...)
|
||||
}
|
||||
|
||||
// AccessSyncById 每日访问数据同步
|
||||
func AccessSyncById(Id string, size int64) (data []VisitLog, err error) {
|
||||
id, err := primitive.ObjectIDFromHex(Id)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
endTime := time.Now().Add(-time.Minute * 5)
|
||||
visitFilter := bson.M{"_id": bson.M{"$gt": id}, "createdAt": bson.M{"$lt": endTime}}
|
||||
visitOpt := (&options.FindOptions{}).SetLimit(size).SetSort(bson.M{"_id": 1})
|
||||
err = coll(nil).Find(&data, visitFilter, visitOpt)
|
||||
return
|
||||
}
|
||||
|
||||
func AccessSyncByTime(visitTime time.Time, size int64) (data []VisitLog, err error) {
|
||||
endTime := time.Now().Add(-time.Minute * 5)
|
||||
visitFilter := bson.M{"createdAt": bson.M{"$gt": visitTime, "$lt": endTime}}
|
||||
visitOpt := (&options.FindOptions{}).SetLimit(size).SetSort(bson.M{"createdAt": 1})
|
||||
err = coll(nil).Find(&data, visitFilter, visitOpt)
|
||||
return
|
||||
}
|
||||
|
||||
func GetInfoByCond(cond bson.M, opts ...*options.FindOneOptions) (VisitLog, error) {
|
||||
v := VisitLog{}
|
||||
if err := coll(nil).FindOne(&v, cond, opts...); err != nil {
|
||||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetInfo", table, "FindOne", err),
|
||||
log.Any("cond", cond),
|
||||
)
|
||||
return v, err
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
Reference in New Issue
Block a user