add: 统计关系
This commit is contained in:
parent
524daccaf3
commit
4964c0c7af
|
@ -11,11 +11,17 @@ import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
var tagCounter = &sync.Map{} // make(map[string]*tagcounter)
|
var tagCounter *tagCounterDict // make(map[string]*tagcounter)
|
||||||
|
|
||||||
|
type tagCounterDict struct {
|
||||||
|
Lock sync.Mutex
|
||||||
|
Data map[string]*tagcounter
|
||||||
|
CountMethodDict map[string]func(args ...string) (*tagcounter, error)
|
||||||
|
}
|
||||||
|
|
||||||
type taginfo struct {
|
type taginfo struct {
|
||||||
Name string
|
Name string
|
||||||
Value int
|
Value int64
|
||||||
}
|
}
|
||||||
|
|
||||||
type tagcounter struct {
|
type tagcounter struct {
|
||||||
|
@ -26,6 +32,13 @@ type tagcounter struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
tagCounter = &tagCounterDict{}
|
||||||
|
tagCounter.Data = map[string]*tagcounter{}
|
||||||
|
tagCounter.CountMethodDict = make(map[string]func(args ...string) (*tagcounter, error))
|
||||||
|
|
||||||
|
tagCounter.CountMethodDict["count"] = countTagWithCountMethod
|
||||||
|
tagCounter.CountMethodDict["followers"] = countTagWithFollersMethod
|
||||||
|
tagCounter.CountMethodDict["gratuity"] = countTagWithGratuityMethod
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,33 +54,21 @@ func CountTag(cxt *gin.Context) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func countTagInfo(cxt *gin.Context, ret func(cxt *gin.Context, cw *tagcounter)) {
|
func countTagWithCountMethod(args ...string) (*tagcounter, error) {
|
||||||
platform := cxt.Query("platform")
|
|
||||||
var cw *tagcounter
|
|
||||||
|
|
||||||
if icw, ok := tagCounter.Load(platform); ok {
|
sqlcount := fmt.Sprintf(SqlTagWithCount, args[0])
|
||||||
cw = icw.(*tagcounter)
|
rows, err := StoreStreamer.Query(sqlcount)
|
||||||
if time.Now().Sub(cw.LastTime).Minutes() <= 10 {
|
|
||||||
ret(cxt, cw)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sql := fmt.Sprintf(SqlTag, platform)
|
|
||||||
rows, err := StoreStreamer.Query(sql)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cxt.Error(err)
|
return nil, err
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cw = &tagcounter{}
|
cw := &tagcounter{}
|
||||||
cw.CountWord = make(map[string]*taginfo)
|
cw.CountWord = make(map[string]*taginfo)
|
||||||
cw.Name = platform
|
|
||||||
cw.LastTime = time.Now()
|
cw.LastTime = time.Now()
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var stag string
|
var stag string
|
||||||
err = rows.Scan(&stag)
|
err := rows.Scan(&stag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
|
@ -82,6 +83,130 @@ func countTagInfo(cxt *gin.Context, ret func(cxt *gin.Context, cw *tagcounter))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return cw, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func countTagWithGratuityMethod(args ...string) (*tagcounter, error) {
|
||||||
|
|
||||||
|
sqlcount := fmt.Sprintf(SqlTagWithAttr, args[0])
|
||||||
|
rows, err := StoreStreamer.Query(sqlcount)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cw := &tagcounter{}
|
||||||
|
cw.CountWord = make(map[string]*taginfo)
|
||||||
|
cw.LastTime = time.Now()
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
var followers, views, gratuity int64
|
||||||
|
var tagsbuf []byte
|
||||||
|
var tags []string
|
||||||
|
rows.Scan(&tagsbuf, &followers, &views, &gratuity)
|
||||||
|
json.Unmarshal(tagsbuf, &tags)
|
||||||
|
if len(tags) > 0 {
|
||||||
|
for _, t := range tags {
|
||||||
|
if _, ok := cw.CountWord[t]; ok {
|
||||||
|
cw.CountWord[t].Value += gratuity
|
||||||
|
} else {
|
||||||
|
cw.CountWord[t] = &taginfo{Name: t, Value: gratuity}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cw, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func countTagWithFollersMethod(args ...string) (*tagcounter, error) {
|
||||||
|
|
||||||
|
sqlcount := fmt.Sprintf(SqlTagWithAttr, args[0])
|
||||||
|
rows, err := StoreStreamer.Query(sqlcount)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cw := &tagcounter{}
|
||||||
|
cw.CountWord = make(map[string]*taginfo)
|
||||||
|
cw.LastTime = time.Now()
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
var followers, views, gratuity int64
|
||||||
|
var tagsbuf []byte
|
||||||
|
var tags []string
|
||||||
|
rows.Scan(&tagsbuf, &followers, &views, &gratuity)
|
||||||
|
json.Unmarshal(tagsbuf, &tags)
|
||||||
|
if len(tags) > 0 {
|
||||||
|
for _, t := range tags {
|
||||||
|
if _, ok := cw.CountWord[t]; ok {
|
||||||
|
cw.CountWord[t].Value += followers
|
||||||
|
} else {
|
||||||
|
cw.CountWord[t] = &taginfo{Name: t, Value: followers}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cw, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func countTagInfo(cxt *gin.Context, ret func(cxt *gin.Context, cw *tagcounter)) {
|
||||||
|
platform := cxt.Query("platform")
|
||||||
|
key := cxt.Query("countkey")
|
||||||
|
|
||||||
|
var cw *tagcounter
|
||||||
|
// var err error
|
||||||
|
|
||||||
|
tagCounter.Lock.Lock()
|
||||||
|
defer tagCounter.Lock.Unlock()
|
||||||
|
|
||||||
|
if icw, ok := tagCounter.Data[platform+key]; ok {
|
||||||
|
cw = icw
|
||||||
|
if time.Now().Sub(cw.LastTime).Minutes() <= 10 {
|
||||||
|
ret(cxt, cw)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sql := fmt.Sprintf(SqlTag, platform)
|
||||||
|
if countMehtod, ok := tagCounter.CountMethodDict[key]; ok {
|
||||||
|
icw, err := countMehtod(platform)
|
||||||
|
if err != nil {
|
||||||
|
cxt.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cw = icw
|
||||||
|
}
|
||||||
|
|
||||||
|
// rows, err := StoreStreamer.Query(sql)
|
||||||
|
// if err != nil {
|
||||||
|
// cxt.Error(err)
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
|
||||||
|
// cw = &tagcounter{}
|
||||||
|
// cw.CountWord = make(map[string]*taginfo)
|
||||||
|
// cw.Name = platform
|
||||||
|
// cw.LastTime = time.Now()
|
||||||
|
|
||||||
|
// for rows.Next() {
|
||||||
|
// var stag string
|
||||||
|
// err = rows.Scan(&stag)
|
||||||
|
// if err != nil {
|
||||||
|
// log.Println(err)
|
||||||
|
// }
|
||||||
|
// var tag []string
|
||||||
|
// json.Unmarshal([]byte(stag), &tag)
|
||||||
|
// for _, t := range tag {
|
||||||
|
// if _, ok := cw.CountWord[t]; ok {
|
||||||
|
// cw.CountWord[t].Value++
|
||||||
|
// } else {
|
||||||
|
// cw.CountWord[t] = &taginfo{Name: t, Value: 1}
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
cw.Name = platform
|
||||||
heap := heap.New(func(a, b interface{}) int {
|
heap := heap.New(func(a, b interface{}) int {
|
||||||
if a.(*taginfo).Value >= b.(*taginfo).Value {
|
if a.(*taginfo).Value >= b.(*taginfo).Value {
|
||||||
return 1
|
return 1
|
||||||
|
@ -91,7 +216,6 @@ func countTagInfo(cxt *gin.Context, ret func(cxt *gin.Context, cw *tagcounter))
|
||||||
})
|
})
|
||||||
|
|
||||||
var other = &taginfo{Name: "Other...", Value: 0}
|
var other = &taginfo{Name: "Other...", Value: 0}
|
||||||
|
|
||||||
for _, v := range cw.CountWord {
|
for _, v := range cw.CountWord {
|
||||||
heap.Put(v)
|
heap.Put(v)
|
||||||
}
|
}
|
||||||
|
@ -115,5 +239,5 @@ func countTagInfo(cxt *gin.Context, ret func(cxt *gin.Context, cw *tagcounter))
|
||||||
cw.PQueue = append(cw.PQueue, other)
|
cw.PQueue = append(cw.PQueue, other)
|
||||||
ret(cxt, cw)
|
ret(cxt, cw)
|
||||||
cw.LastTime = time.Now()
|
cw.LastTime = time.Now()
|
||||||
tagCounter.Store(platform, cw)
|
tagCounter.Data[platform+key] = cw
|
||||||
}
|
}
|
||||||
|
|
124
goserver/main.go
124
goserver/main.go
|
@ -2,11 +2,8 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -82,127 +79,6 @@ type ObjectQuery struct {
|
||||||
UpdateTime *time.Time
|
UpdateTime *time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func Query(cxt *gin.Context, platform string) {
|
|
||||||
var err error
|
|
||||||
page, err := strconv.Atoi(cxt.Query("page"))
|
|
||||||
if err != nil {
|
|
||||||
cxt.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
psize, err := strconv.Atoi(cxt.Query("psize"))
|
|
||||||
if err != nil {
|
|
||||||
cxt.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if psize > 5000 {
|
|
||||||
cxt.Error(fmt.Errorf("page size <= 5000"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// filter := cxt.Query("filter")
|
|
||||||
orderfield := cxt.Query("orderfield")
|
|
||||||
ordertype := cxt.Query("ordertype")
|
|
||||||
|
|
||||||
log.Println(orderfield, ordertype)
|
|
||||||
|
|
||||||
start := (page - 1) * psize
|
|
||||||
// end := start + 200
|
|
||||||
|
|
||||||
var orderstr string
|
|
||||||
switch ordertype {
|
|
||||||
case "ascend":
|
|
||||||
orderstr = fmt.Sprintf("ORDER BY %s ASC", orderfield)
|
|
||||||
case "descend":
|
|
||||||
orderstr = fmt.Sprintf("ORDER BY %s DESC", orderfield)
|
|
||||||
default:
|
|
||||||
orderstr = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
ssql := fmt.Sprintf(SqlQuery, platform, orderstr, strconv.Itoa(start), strconv.Itoa(psize))
|
|
||||||
rows, err := StoreStreamer.Query(ssql)
|
|
||||||
if err != nil {
|
|
||||||
cxt.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var ots []*ObjectQuery
|
|
||||||
for rows.Next() {
|
|
||||||
ot := &ObjectQuery{}
|
|
||||||
var view, gratuity sql.NullInt64
|
|
||||||
var lstm, letm, utm sql.NullTime
|
|
||||||
var username, tags, livetitle, liveurl sql.NullString
|
|
||||||
err = rows.Scan(
|
|
||||||
&ot.Uid,
|
|
||||||
&ot.Platform,
|
|
||||||
&ot.UserId,
|
|
||||||
&username,
|
|
||||||
&liveurl,
|
|
||||||
&tags,
|
|
||||||
&ot.Followers,
|
|
||||||
&view,
|
|
||||||
&gratuity,
|
|
||||||
&livetitle,
|
|
||||||
&lstm,
|
|
||||||
&letm,
|
|
||||||
&utm,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
cxt.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !lstm.Valid {
|
|
||||||
ot.LiveStartTime = nil
|
|
||||||
} else {
|
|
||||||
ot.LiveStartTime = &lstm.Time
|
|
||||||
}
|
|
||||||
if !letm.Valid {
|
|
||||||
ot.LiveEndTime = nil
|
|
||||||
} else {
|
|
||||||
ot.LiveEndTime = &letm.Time
|
|
||||||
}
|
|
||||||
if !utm.Valid {
|
|
||||||
ot.UpdateTime = nil
|
|
||||||
} else {
|
|
||||||
ot.UpdateTime = &utm.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
if livetitle.Valid {
|
|
||||||
ot.LiveTitle = livetitle.String
|
|
||||||
}
|
|
||||||
|
|
||||||
if view.Valid {
|
|
||||||
ot.Views = view.Int64
|
|
||||||
}
|
|
||||||
|
|
||||||
if gratuity.Valid {
|
|
||||||
ot.Gratuity = gratuity.Int64
|
|
||||||
}
|
|
||||||
|
|
||||||
if username.Valid {
|
|
||||||
ot.UserName = username.String
|
|
||||||
}
|
|
||||||
|
|
||||||
if liveurl.Valid {
|
|
||||||
ot.LiveUrl = liveurl.String
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = json.Unmarshal([]byte(tags.String), &ot.Tags); err != nil {
|
|
||||||
// log.Println(tags)
|
|
||||||
}
|
|
||||||
|
|
||||||
ots = append(ots, ot)
|
|
||||||
}
|
|
||||||
|
|
||||||
r := &Result{Code: 200}
|
|
||||||
r.Data = ots
|
|
||||||
// log.Println(len(ots))
|
|
||||||
if retdata, err := json.Marshal(r); err != nil {
|
|
||||||
cxt.Error(err)
|
|
||||||
} else {
|
|
||||||
cxt.JSON(r.Code, string(retdata))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
engine := gin.New() //r := gin.Default() //使用默认中间件
|
engine := gin.New() //r := gin.Default() //使用默认中间件
|
||||||
engine.Use(gin.Logger())
|
engine.Use(gin.Logger())
|
||||||
|
|
|
@ -44,37 +44,52 @@ func estCountTag(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func estDupTag(t *testing.T) {
|
func estDupTag(t *testing.T) {
|
||||||
querysql := "select uid, tags from streamer where tags is not null"
|
querysql := `SELECT
|
||||||
rows, err := StoreStreamer.Query(querysql)
|
|
||||||
|
ie.tags ,
|
||||||
|
cl.followers ,
|
||||||
|
cl.views ,
|
||||||
|
cl.gratuity
|
||||||
|
From
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
intimate_extractor.streamer
|
||||||
|
WHERE
|
||||||
|
platform = "%s"
|
||||||
|
AND operator = 0
|
||||||
|
AND latest_log_uid is not NULL ) ie
|
||||||
|
JOIN intimate_extractor.collect_log cl
|
||||||
|
WHERE
|
||||||
|
ie.latest_log_uid = cl.log_uid %s;`
|
||||||
|
|
||||||
|
sortstr := "order by cl.followers desc"
|
||||||
|
|
||||||
|
rows, err := StoreStreamer.Query(querysql, "twitch", sortstr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var counttag = make(map[string]int64)
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var uid int64
|
var followers, views, gratuity int64
|
||||||
var tagsbuf []byte
|
var tagsbuf []byte
|
||||||
var tags []string
|
var tags []string
|
||||||
rows.Scan(&uid, &tagsbuf)
|
rows.Scan(&tagsbuf, &followers, &views, &gratuity)
|
||||||
json.Unmarshal(tagsbuf, &tags)
|
json.Unmarshal(tagsbuf, &tags)
|
||||||
if len(tags) > 0 {
|
if len(tags) > 0 {
|
||||||
var newtags []string
|
|
||||||
m := make(map[string]int)
|
|
||||||
for _, t := range tags {
|
for _, t := range tags {
|
||||||
if _, ok := m[t]; !ok {
|
if _, ok := counttag[t]; ok {
|
||||||
newtags = append(newtags, t)
|
counttag[t] += gratuity
|
||||||
m[t] = 1
|
|
||||||
} else {
|
} else {
|
||||||
m[t]++
|
counttag[t] = gratuity
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(newtags) != len(tags) {
|
|
||||||
t.Error(uid, tags)
|
|
||||||
newtagsbuf, err := json.Marshal(newtags)
|
|
||||||
if err == nil {
|
|
||||||
StoreStreamer.Exec("update streamer set tags = ? where uid = ?", newtagsbuf, uid)
|
|
||||||
} else {
|
|
||||||
panic(err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTagFollowers(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package main
|
||||||
|
|
||||||
import "github.com/gin-gonic/gin"
|
import "github.com/gin-gonic/gin"
|
||||||
|
|
||||||
|
// OpenrecQuery Openrec的查询API
|
||||||
func OpenrecQuery(cxt *gin.Context) {
|
func OpenrecQuery(cxt *gin.Context) {
|
||||||
Query(cxt, "openrec")
|
Query(cxt, "openrec")
|
||||||
}
|
}
|
||||||
|
|
133
goserver/query_data.go
Normal file
133
goserver/query_data.go
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Query 查询表数据的API 方法
|
||||||
|
func Query(cxt *gin.Context, platform string) {
|
||||||
|
var err error
|
||||||
|
page, err := strconv.Atoi(cxt.Query("page"))
|
||||||
|
if err != nil {
|
||||||
|
cxt.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
psize, err := strconv.Atoi(cxt.Query("psize"))
|
||||||
|
if err != nil {
|
||||||
|
cxt.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if psize > 5000 {
|
||||||
|
cxt.Error(fmt.Errorf("page size <= 5000"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// filter := cxt.Query("filter")
|
||||||
|
orderfield := cxt.Query("orderfield")
|
||||||
|
ordertype := cxt.Query("ordertype")
|
||||||
|
|
||||||
|
log.Println(orderfield, ordertype)
|
||||||
|
|
||||||
|
start := (page - 1) * psize
|
||||||
|
// end := start + 200
|
||||||
|
|
||||||
|
var orderstr string
|
||||||
|
switch ordertype {
|
||||||
|
case "ascend":
|
||||||
|
orderstr = fmt.Sprintf("ORDER BY %s ASC", orderfield)
|
||||||
|
case "descend":
|
||||||
|
orderstr = fmt.Sprintf("ORDER BY %s DESC", orderfield)
|
||||||
|
default:
|
||||||
|
orderstr = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
ssql := fmt.Sprintf(SqlQuery, platform, orderstr, strconv.Itoa(start), strconv.Itoa(psize))
|
||||||
|
rows, err := StoreStreamer.Query(ssql)
|
||||||
|
if err != nil {
|
||||||
|
cxt.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var ots []*ObjectQuery
|
||||||
|
for rows.Next() {
|
||||||
|
ot := &ObjectQuery{}
|
||||||
|
var views, gratuity sql.NullInt64
|
||||||
|
var lstm, letm, utm sql.NullTime
|
||||||
|
var username, tags, livetitle, liveurl sql.NullString
|
||||||
|
err = rows.Scan(
|
||||||
|
&ot.Uid,
|
||||||
|
&ot.Platform,
|
||||||
|
&ot.UserId,
|
||||||
|
&username,
|
||||||
|
&liveurl,
|
||||||
|
&tags,
|
||||||
|
&ot.Followers,
|
||||||
|
&views,
|
||||||
|
&gratuity,
|
||||||
|
&livetitle,
|
||||||
|
&lstm,
|
||||||
|
&letm,
|
||||||
|
&utm,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
cxt.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !lstm.Valid {
|
||||||
|
ot.LiveStartTime = nil
|
||||||
|
} else {
|
||||||
|
ot.LiveStartTime = &lstm.Time
|
||||||
|
}
|
||||||
|
if !letm.Valid {
|
||||||
|
ot.LiveEndTime = nil
|
||||||
|
} else {
|
||||||
|
ot.LiveEndTime = &letm.Time
|
||||||
|
}
|
||||||
|
if !utm.Valid {
|
||||||
|
ot.UpdateTime = nil
|
||||||
|
} else {
|
||||||
|
ot.UpdateTime = &utm.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
if livetitle.Valid {
|
||||||
|
ot.LiveTitle = livetitle.String
|
||||||
|
}
|
||||||
|
|
||||||
|
if views.Valid {
|
||||||
|
ot.Views = views.Int64
|
||||||
|
}
|
||||||
|
|
||||||
|
if gratuity.Valid {
|
||||||
|
ot.Gratuity = gratuity.Int64
|
||||||
|
}
|
||||||
|
|
||||||
|
if username.Valid {
|
||||||
|
ot.UserName = username.String
|
||||||
|
}
|
||||||
|
|
||||||
|
if liveurl.Valid {
|
||||||
|
ot.LiveUrl = liveurl.String
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = json.Unmarshal([]byte(tags.String), &ot.Tags); err != nil {
|
||||||
|
// log.Println(tags)
|
||||||
|
}
|
||||||
|
|
||||||
|
ots = append(ots, ot)
|
||||||
|
}
|
||||||
|
|
||||||
|
r := &Result{Code: 200}
|
||||||
|
r.Data = ots
|
||||||
|
// log.Println(len(ots))
|
||||||
|
if retdata, err := json.Marshal(r); err != nil {
|
||||||
|
cxt.Error(err)
|
||||||
|
} else {
|
||||||
|
cxt.JSON(r.Code, string(retdata))
|
||||||
|
}
|
||||||
|
}
|
77
goserver/screenlog.0
Normal file
77
goserver/screenlog.0
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
2020/08/24 16:31:09 find config: ./config.yaml
|
||||||
|
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
|
||||||
|
- using env: export GIN_MODE=release
|
||||||
|
- using code: gin.SetMode(gin.ReleaseMode)
|
||||||
|
|
||||||
|
[GIN-debug] GET /twitcasting/query --> main.TwitcastingQuery (3 handlers)
|
||||||
|
[GIN-debug] GET /openrec/query --> main.OpenrecQuery (3 handlers)
|
||||||
|
[GIN-debug] GET /twitch/query --> main.TwitchQuery (3 handlers)
|
||||||
|
[GIN-debug] GET /tag/count --> main.CountTag (3 handlers)
|
||||||
|
[GIN-debug] GET /tag/allcount --> main.CountTag (3 handlers)
|
||||||
|
[GIN-debug] Listening and serving HTTP on :5500
|
||||||
|
16:33:16 /home/eson/test/create-react-app-antd/goserver/query_data.go:35: followers descend
|
||||||
|
[GIN] 2020/08/24 - 16:33:17 |[97;42m 200 [0m| 397.857448ms | 192.168.16.130 |[97;44m GET [0m "/twitcasting/query?page=1&psize=20&orderfield=followers&ordertype=descend"
|
||||||
|
[GIN] 2020/08/24 - 16:33:17 |[97;42m 200 [0m| 630.949609ms | 192.168.16.130 |[97;44m GET [0m "/tag/count?platform=twitcasting"
|
||||||
|
16:33:18 /home/eson/test/create-react-app-antd/goserver/query_data.go:35: followers descend
|
||||||
|
[GIN] 2020/08/24 - 16:33:18 |[97;42m 200 [0m| 251.472068ms | 192.168.16.130 |[97;44m GET [0m "/twitcasting/query?page=1&psize=20&orderfield=followers&ordertype=descend"
|
||||||
|
16:36:32 /home/eson/test/create-react-app-antd/goserver/query_data.go:35:
|
||||||
|
[GIN] 2020/08/24 - 16:36:32 |[97;42m 200 [0m| 65.723084ms | 192.168.16.130 |[97;44m GET [0m "/openrec/query?page=1&psize=20"
|
||||||
|
16:36:32 /home/eson/test/create-react-app-antd/goserver/query_data.go:35:
|
||||||
|
[GIN] 2020/08/24 - 16:36:32 |[97;42m 200 [0m| 67.82141ms | 192.168.16.103 |[97;44m GET [0m "/openrec/query?page=1&psize=20"
|
||||||
|
16:36:33 /home/eson/test/create-react-app-antd/goserver/query_data.go:35:
|
||||||
|
[GIN] 2020/08/24 - 16:36:33 |[97;42m 200 [0m| 62.965398ms | 192.168.16.130 |[97;44m GET [0m "/openrec/query?page=1&psize=20"
|
||||||
|
16:36:37 /home/eson/test/create-react-app-antd/goserver/query_data.go:35:
|
||||||
|
[GIN] 2020/08/24 - 16:36:38 |[97;42m 200 [0m| 231.238484ms | 192.168.16.130 |[97;44m GET [0m "/twitch/query?page=1&psize=20"
|
||||||
|
16:37:23 /home/eson/test/create-react-app-antd/goserver/query_data.go:35:
|
||||||
|
[GIN] 2020/08/24 - 16:37:23 |[97;42m 200 [0m| 77.816922ms | 192.168.16.103 |[97;44m GET [0m "/openrec/query?page=1&psize=20"
|
||||||
|
16:37:23 /home/eson/test/create-react-app-antd/goserver/query_data.go:35:
|
||||||
|
[GIN] 2020/08/24 - 16:37:23 |[97;42m 200 [0m| 60.302602ms | 192.168.16.130 |[97;44m GET [0m "/openrec/query?page=1&psize=20"
|
||||||
|
16:37:24 /home/eson/test/create-react-app-antd/goserver/query_data.go:35:
|
||||||
|
[GIN] 2020/08/24 - 16:37:24 |[97;42m 200 [0m| 55.982297ms | 192.168.16.130 |[97;44m GET [0m "/openrec/query?page=1&psize=20"
|
||||||
|
16:37:28 /home/eson/test/create-react-app-antd/goserver/query_data.go:35: views descend
|
||||||
|
[GIN] 2020/08/24 - 16:37:28 |[97;42m 200 [0m| 72.116427ms | 192.168.16.130 |[97;44m GET [0m "/openrec/query?page=1&psize=20&orderfield=views&ordertype=descend"
|
||||||
|
16:37:32 /home/eson/test/create-react-app-antd/goserver/query_data.go:35: views ascend
|
||||||
|
[GIN] 2020/08/24 - 16:37:32 |[97;42m 200 [0m| 60.815908ms | 192.168.16.130 |[97;44m GET [0m "/openrec/query?page=1&psize=20&orderfield=views&ordertype=ascend"
|
||||||
|
16:37:33 /home/eson/test/create-react-app-antd/goserver/query_data.go:35: undefined
|
||||||
|
[GIN] 2020/08/24 - 16:37:33 |[97;42m 200 [0m| 49.692998ms | 192.168.16.130 |[97;44m GET [0m "/openrec/query?page=1&psize=20&orderfield=&ordertype=undefined"
|
||||||
|
16:37:35 /home/eson/test/create-react-app-antd/goserver/query_data.go:35: undefined
|
||||||
|
[GIN] 2020/08/24 - 16:37:36 |[97;42m 200 [0m| 138.6536ms | 192.168.16.130 |[97;44m GET [0m "/twitcasting/query?page=1&psize=20&orderfield=&ordertype=undefined"
|
||||||
|
16:37:42 /home/eson/test/create-react-app-antd/goserver/query_data.go:35: views descend
|
||||||
|
[GIN] 2020/08/24 - 16:37:43 |[97;42m 200 [0m| 275.719131ms | 192.168.16.130 |[97;44m GET [0m "/twitcasting/query?page=1&psize=20&orderfield=views&ordertype=descend"
|
||||||
|
16:37:44 /home/eson/test/create-react-app-antd/goserver/query_data.go:35: views ascend
|
||||||
|
[GIN] 2020/08/24 - 16:37:44 |[97;42m 200 [0m| 300.06176ms | 192.168.16.130 |[97;44m GET [0m "/twitcasting/query?page=1&psize=20&orderfield=views&ordertype=ascend"
|
||||||
|
16:37:45 /home/eson/test/create-react-app-antd/goserver/query_data.go:35: undefined
|
||||||
|
[GIN] 2020/08/24 - 16:37:45 |[97;42m 200 [0m| 226.08364ms | 192.168.16.130 |[97;44m GET [0m "/twitcasting/query?page=1&psize=20&orderfield=&ordertype=undefined"
|
||||||
|
16:37:46 /home/eson/test/create-react-app-antd/goserver/query_data.go:35: views descend
|
||||||
|
[GIN] 2020/08/24 - 16:37:46 |[97;42m 200 [0m| 250.248182ms | 192.168.16.130 |[97;44m GET [0m "/twitcasting/query?page=1&psize=20&orderfield=views&ordertype=descend"
|
||||||
|
16:37:54 /home/eson/test/create-react-app-antd/goserver/query_data.go:35:
|
||||||
|
[GIN] 2020/08/24 - 16:37:54 |[97;42m 200 [0m| 54.738324ms | 192.168.16.130 |[97;44m GET [0m "/openrec/query?page=1&psize=20"
|
||||||
|
16:37:54 /home/eson/test/create-react-app-antd/goserver/query_data.go:35:
|
||||||
|
[GIN] 2020/08/24 - 16:37:54 |[97;42m 200 [0m| 52.897355ms | 192.168.16.103 |[97;44m GET [0m "/openrec/query?page=1&psize=20"
|
||||||
|
16:37:54 /home/eson/test/create-react-app-antd/goserver/query_data.go:35:
|
||||||
|
[GIN] 2020/08/24 - 16:37:54 |[97;42m 200 [0m| 36.935769ms | 192.168.16.130 |[97;44m GET [0m "/openrec/query?page=1&psize=20"
|
||||||
|
16:37:56 /home/eson/test/create-react-app-antd/goserver/query_data.go:35: views descend
|
||||||
|
[GIN] 2020/08/24 - 16:37:56 |[97;42m 200 [0m| 57.870346ms | 192.168.16.130 |[97;44m GET [0m "/openrec/query?page=1&psize=20&orderfield=views&ordertype=descend"
|
||||||
|
16:37:58 /home/eson/test/create-react-app-antd/goserver/query_data.go:35: views descend
|
||||||
|
[GIN] 2020/08/24 - 16:37:59 |[97;42m 200 [0m| 315.446812ms | 192.168.16.130 |[97;44m GET [0m "/twitch/query?page=1&psize=20&orderfield=views&ordertype=descend"
|
||||||
|
16:38:00 /home/eson/test/create-react-app-antd/goserver/query_data.go:35: views ascend
|
||||||
|
[GIN] 2020/08/24 - 16:38:00 |[97;42m 200 [0m| 233.687395ms | 192.168.16.130 |[97;44m GET [0m "/twitch/query?page=1&psize=20&orderfield=views&ordertype=ascend"
|
||||||
|
16:38:01 /home/eson/test/create-react-app-antd/goserver/query_data.go:35: undefined
|
||||||
|
[GIN] 2020/08/24 - 16:38:01 |[97;42m 200 [0m| 226.263587ms | 192.168.16.130 |[97;44m GET [0m "/twitch/query?page=1&psize=20&orderfield=&ordertype=undefined"
|
||||||
|
16:38:02 /home/eson/test/create-react-app-antd/goserver/query_data.go:35: views descend
|
||||||
|
[GIN] 2020/08/24 - 16:38:02 |[97;42m 200 [0m| 219.708245ms | 192.168.16.130 |[97;44m GET [0m "/twitch/query?page=1&psize=20&orderfield=views&ordertype=descend"
|
||||||
|
16:38:09 /home/eson/test/create-react-app-antd/goserver/query_data.go:35: views descend
|
||||||
|
[GIN] 2020/08/24 - 16:38:09 |[97;42m 200 [0m| 311.05848ms | 192.168.16.130 |[97;44m GET [0m "/twitcasting/query?page=1&psize=20&orderfield=views&ordertype=descend"
|
||||||
|
[GIN] 2020/08/24 - 16:40:23 |[97;42m 200 [0m| 114.314µs | 192.168.16.130 |[97;44m GET [0m "/tag/count?platform=twitcasting"
|
||||||
|
17:50:21 /home/eson/test/create-react-app-antd/goserver/query_data.go:35:
|
||||||
|
[GIN] 2020/08/24 - 17:50:21 |[97;42m 200 [0m| 48.105852ms | 192.168.16.130 |[97;44m GET [0m "/openrec/query?page=1&psize=20"
|
||||||
|
17:50:21 /home/eson/test/create-react-app-antd/goserver/query_data.go:35:
|
||||||
|
[GIN] 2020/08/24 - 17:50:21 |[97;42m 200 [0m| 29.279913ms | 192.168.16.103 |[97;44m GET [0m "/openrec/query?page=1&psize=20"
|
||||||
|
17:50:36 /home/eson/test/create-react-app-antd/goserver/query_data.go:35:
|
||||||
|
[GIN] 2020/08/24 - 17:50:36 |[97;42m 200 [0m| 28.115392ms | 192.168.16.130 |[97;44m GET [0m "/openrec/query?page=1&psize=20"
|
||||||
|
17:50:37 /home/eson/test/create-react-app-antd/goserver/query_data.go:35:
|
||||||
|
[GIN] 2020/08/24 - 17:50:37 |[97;42m 200 [0m| 40.507783ms | 192.168.16.103 |[97;44m GET [0m "/openrec/query?page=1&psize=20"
|
||||||
|
17:53:07 /home/eson/test/create-react-app-antd/goserver/query_data.go:35:
|
||||||
|
[GIN] 2020/08/24 - 17:53:07 |[97;42m 200 [0m| 22.445236ms | 192.168.16.130 |[97;44m GET [0m "/openrec/query?page=1&psize=20"
|
||||||
|
[GIN] 2020/08/24 - 17:53:08 |[97;42m 200 [0m| 42.924993ms | 192.168.16.130 |[97;44m GET [0m "/tag/count?platform=openrec&countkey=count"
|
||||||
|
^[[A^[[A^[[A^[[B^[[B^[[B^C
|
|
@ -1,7 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
// SqlTag 获取 tag
|
// SqlTagWithCount 获取 tag
|
||||||
var SqlTag string = `SELECT tags FROM intimate_extractor.streamer
|
var SqlTagWithCount string = `SELECT tags FROM intimate_extractor.streamer
|
||||||
WHERE platform = "%s" AND tags IS NOT NULL`
|
WHERE platform = "%s" AND tags IS NOT NULL`
|
||||||
|
|
||||||
//SqlQuery 获取 网站数据
|
//SqlQuery 获取 网站数据
|
||||||
|
@ -32,3 +32,25 @@ WHERE
|
||||||
JOIN intimate_extractor.collect_log cl
|
JOIN intimate_extractor.collect_log cl
|
||||||
WHERE
|
WHERE
|
||||||
ie.latest_log_uid = cl.log_uid %s limit %s,%s;`
|
ie.latest_log_uid = cl.log_uid %s limit %s,%s;`
|
||||||
|
|
||||||
|
var SqlTagWithAttr = `SELECT
|
||||||
|
|
||||||
|
ie.tags ,
|
||||||
|
cl.followers ,
|
||||||
|
cl.views ,
|
||||||
|
cl.gratuity
|
||||||
|
From
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
intimate_extractor.streamer
|
||||||
|
WHERE
|
||||||
|
platform = "%s"
|
||||||
|
AND operator = 0
|
||||||
|
AND latest_log_uid is not NULL ) ie
|
||||||
|
JOIN intimate_extractor.collect_log cl
|
||||||
|
WHERE
|
||||||
|
ie.latest_log_uid = cl.log_uid;`
|
||||||
|
|
||||||
|
// sortstr := "order by cl.followers desc"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactEcharts from 'echarts-for-react';
|
import ReactEcharts from 'echarts-for-react';
|
||||||
import apihost from './Var.js';
|
import apihost from './Var.js';
|
||||||
|
import { Row, Col, Button } from 'antd';
|
||||||
|
|
||||||
function parseData(cw = {}) {
|
function parseData(cw = {}) {
|
||||||
|
|
||||||
|
@ -39,10 +40,10 @@ function parseData(cw = {}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getOption(state = {}) {
|
function getOption(state = {}) {
|
||||||
const { platform, data } = state;
|
const { platform, data, title } = state;
|
||||||
const option = {
|
const option = {
|
||||||
title: {
|
title: {
|
||||||
text: `${platform}同名数量统计`,
|
text: `${platform}${title}`,
|
||||||
subtext: '数据最新仅供参考',
|
subtext: '数据最新仅供参考',
|
||||||
left: 'center'
|
left: 'center'
|
||||||
},
|
},
|
||||||
|
@ -85,7 +86,9 @@ class ChartsCount extends React.Component {
|
||||||
state = {
|
state = {
|
||||||
option: {},
|
option: {},
|
||||||
platform: this.props.platform,
|
platform: this.props.platform,
|
||||||
data: {}
|
data: {},
|
||||||
|
countkey: "count",
|
||||||
|
title: "统计数量关系",
|
||||||
}
|
}
|
||||||
|
|
||||||
changePlatform = (p) => {
|
changePlatform = (p) => {
|
||||||
|
@ -95,8 +98,8 @@ class ChartsCount extends React.Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
updateData = () => {
|
updateData = () => {
|
||||||
const { platform } = this.state;
|
const { countkey, platform } = this.state;
|
||||||
fetch(`${apihost}/tag/count?platform=${platform}`, {
|
fetch(`${apihost}/tag/count?platform=${platform}&countkey=${countkey}`, {
|
||||||
"mode": "cors"
|
"mode": "cors"
|
||||||
}).then(
|
}).then(
|
||||||
response => {
|
response => {
|
||||||
|
@ -117,16 +120,32 @@ class ChartsCount extends React.Component {
|
||||||
this.updateData();
|
this.updateData();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
countMethod(countkey, title) {
|
||||||
return (<div style={{ padding: 24, background: '#fff', minHeight: 780 }} >
|
this.setState({countkey: countkey, title: title}, ()=>{this.updateData()});
|
||||||
<ReactEcharts
|
}
|
||||||
notMerge={true}
|
|
||||||
ref={(e) => { this.echarts_react = e; }}
|
|
||||||
option={getOption(this.state)}
|
|
||||||
style={{ height: '600px', width: '100%' }}
|
|
||||||
className='react_for_echarts' />
|
|
||||||
|
|
||||||
</div>
|
render() {
|
||||||
|
return (
|
||||||
|
<div style={{ padding: 24, background: '#fff', minHeight: 780 }} >
|
||||||
|
<div style={{ marginBottom: "20px" }}>
|
||||||
|
<Row justify="start">
|
||||||
|
<Col span={3}> <Button type="primary" onClick={(e)=>{ this.countMethod("count", e.target.innerText) }} >统计数量关系</Button> </Col>
|
||||||
|
<Col span={3}>
|
||||||
|
<Button type="primary" onClick={(e)=>{
|
||||||
|
this.countMethod("followers", e.target.innerText)
|
||||||
|
}}>统计关注关系</Button>
|
||||||
|
</Col>
|
||||||
|
<Col span={3}> <Button type="primary" onClick={(e)=>{ this.countMethod("gratuity", e.target.innerText) }} >统计赏币关系</Button> </Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
<ReactEcharts
|
||||||
|
notMerge={true}
|
||||||
|
ref={(e) => { this.echarts_react = e; }}
|
||||||
|
option={getOption(this.state)}
|
||||||
|
style={{ height: '600px', width: '100%' }}
|
||||||
|
className='react_for_echarts' />
|
||||||
|
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
23
src/Table.js
23
src/Table.js
|
@ -71,8 +71,8 @@ class DataTable extends React.Component {
|
||||||
updatePlatform(p) {
|
updatePlatform(p) {
|
||||||
|
|
||||||
const { pagination, sorter, filters } = this.state;
|
const { pagination, sorter, filters } = this.state;
|
||||||
console.log("filters", filters); // ${filters?`&filters=${filters}`:""}
|
// console.log("filters", filters); // ${filters?`&filters=${filters}`:""}
|
||||||
console.log("sorter", sorter);
|
// console.log("sorter", sorter);
|
||||||
pagination.current = 1;
|
pagination.current = 1;
|
||||||
this.setState({ platform: p }, () => {
|
this.setState({ platform: p }, () => {
|
||||||
this.fetchapi({
|
this.fetchapi({
|
||||||
|
@ -103,8 +103,8 @@ class DataTable extends React.Component {
|
||||||
const { pagination, sorter, filters } = params;
|
const { pagination, sorter, filters } = params;
|
||||||
const { platform, } = this.state;
|
const { platform, } = this.state;
|
||||||
this.setState({ loading: true });
|
this.setState({ loading: true });
|
||||||
console.log("filters", filters); // ${filters?`&filters=${filters}`:""}
|
// console.log("filters", filters); // ${filters?`&filters=${filters}`:""}
|
||||||
console.log("sorter", sorter);
|
// console.log("sorter", sorter);
|
||||||
fetch(`${apihost}/${platform}/query?page=${pagination.current}&psize=${pagination.pageSize}${sorter?`&orderfield=${sorter.column?sorter.column.dataField:""}&ordertype=${sorter.order}`:""}`, { mode: "cors" }).then((response) => {
|
fetch(`${apihost}/${platform}/query?page=${pagination.current}&psize=${pagination.pageSize}${sorter?`&orderfield=${sorter.column?sorter.column.dataField:""}&ordertype=${sorter.order}`:""}`, { mode: "cors" }).then((response) => {
|
||||||
// console.log(response);
|
// console.log(response);
|
||||||
response.json().then(
|
response.json().then(
|
||||||
|
@ -128,8 +128,8 @@ class DataTable extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
|
|
||||||
let { data, pagination, loading, sorter, filters } = this.state;
|
let { data, pagination, loading, sorter, filters } = this.state;
|
||||||
sorter = sorter || {};
|
// sorter = sorter || {};
|
||||||
filters = filters || {};
|
// filters = filters || {};
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
|
@ -156,6 +156,17 @@ class DataTable extends React.Component {
|
||||||
dataField: 'user_name',
|
dataField: 'user_name',
|
||||||
// width: "7%",
|
// width: "7%",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '观众数',
|
||||||
|
dataIndex: 'Views',
|
||||||
|
editable: false,
|
||||||
|
key: 'Views',
|
||||||
|
dataField: 'views',
|
||||||
|
sorter: (a, b) => a.Views - b.Views,
|
||||||
|
sortDirections: ['descend', 'ascend'],
|
||||||
|
ellipsis: false,
|
||||||
|
// width: "7%",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '标签',
|
title: '标签',
|
||||||
dataIndex: 'Tags',
|
dataIndex: 'Tags',
|
||||||
|
|
Loading…
Reference in New Issue
Block a user