mysql.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. package dao
  2. import (
  3. "context"
  4. "fmt"
  5. "time"
  6. artmdl "go-common/app/interface/openplatform/article/model"
  7. "go-common/app/job/openplatform/article/model"
  8. "go-common/library/database/sql"
  9. "go-common/library/log"
  10. "go-common/library/xstr"
  11. )
  12. const (
  13. _sharding = 100
  14. // stat
  15. _statSQL = "SELECT article_id,favorite,reply,share,likes,dislike,view,coin FROM article_stats_%s WHERE article_id=%d and deleted_time =0"
  16. _upStatSQL = `INSERT INTO article_stats_%s (article_id,favorite,reply,share,likes,dislike,view,coin) VALUES (?,?,?,?,?,?,?,?)
  17. ON DUPLICATE KEY UPDATE favorite=?,reply=?,share=?,likes=?,dislike=?,view=?,coin=?`
  18. _updateSearch = `INSERT INTO search_articles(ctime, article_id, category_id, title, summary, template_id, mid, image_urls, publish_time, content, tags, stats_view, stats_favorite, stats_likes, stats_dislike, stats_reply, stats_share, stats_coin, origin_image_urls, attributes, keywords)
  19. VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) ON DUPLICATE KEY UPDATE ctime = ?, category_id =?, title=?, summary=?, template_id=?, mid=?, image_urls=?, publish_time=?, content=?, tags=?, stats_view=?, stats_favorite=?, stats_likes=?, stats_dislike=?, stats_reply=?, stats_share=?, stats_coin = ?, origin_image_urls = ?, attributes = ?, keywords = ?`
  20. _delSearch = "DELETE FROM search_articles where article_id = ?"
  21. _articleContentSQL = "SELECT content FROM filtered_article_contents_%s WHERE article_id = ?"
  22. _updateSearchStats = "UPDATE search_articles SET stats_view=?, stats_favorite=?, stats_likes=?, stats_dislike=?, stats_reply=?, stats_share=?, stats_coin =? where article_id = ?"
  23. _gameList = "SELECT mid FROM white_list_users WHERE group_id = 4 AND deleted = 0"
  24. _allCheat = "SELECT article_id, lv FROM stats_filters WHERE deleted_time = 0"
  25. _newestArtsMetaSQL = "SELECT article_id, publish_time, attributes FROM filtered_articles ORDER BY publish_time DESC LIMIT ?"
  26. _newestArtCategorysMetaSQL = "SELECT article_id, publish_time, attributes FROM filtered_articles where category_id in (%s) ORDER BY publish_time DESC LIMIT %d"
  27. _searchArticles = "select article_id, category_id, attributes, stats_view, stats_reply, stats_favorite, stats_likes, stats_coin from search_articles where publish_time >= ? and publish_time < ?"
  28. _checkStateSQL = "SELECT publish_time,check_state FROM articles WHERE id = ? and deleted_time = 0"
  29. _updateCheckState = "UPDATE articles SET check_state = 3 WHERE id = ?"
  30. _settingsSQL = "SELECT name,value FROM article_settings WHERE deleted_time=0"
  31. _midsByPublishTimeSQL = "SELECT mid FROM articles WHERE publish_time > ? and state = 0 and deleted_time = 0 group by mid"
  32. _statByMidSQL = "select count(*), sum(words), category_id from articles where mid = ? and state = 0 and deleted_time = 0 group by category_id"
  33. _keywordsSQL = "select tags from article_contents_%s where article_id = ?"
  34. _actIDSQL = "select act_id from articles where id = ?"
  35. _lastModsArtsSQL = "select id from articles where state in (0,5,6,7) and deleted_time = 0 order by mtime desc limit ?"
  36. )
  37. var _searchInterval = int64(3 * 24 * 3600)
  38. func (d *Dao) hit(id int64) string {
  39. return fmt.Sprintf("%02d", id%_sharding)
  40. }
  41. // Stat returns stat info.
  42. func (d *Dao) Stat(c context.Context, aid int64) (stat *artmdl.StatMsg, err error) {
  43. stat = &artmdl.StatMsg{}
  44. err = d.db.QueryRow(c, fmt.Sprintf(_statSQL, d.hit(aid), aid)).Scan(&stat.Aid, &stat.Favorite, &stat.Reply, &stat.Share, &stat.Like, &stat.Dislike, &stat.View, &stat.Coin)
  45. if err == sql.ErrNoRows {
  46. err = nil
  47. stat = nil
  48. } else if err != nil {
  49. log.Error("Stat(%v) error(%+v)", aid, err)
  50. PromError("db:读取计数")
  51. }
  52. return
  53. }
  54. // Update updates stat in db.
  55. func (d *Dao) Update(c context.Context, stat *artmdl.StatMsg) (rows int64, err error) {
  56. res, err := d.db.Exec(c, fmt.Sprintf(_upStatSQL, d.hit(stat.Aid)), stat.Aid, *stat.Favorite, *stat.Reply, *stat.Share, *stat.Like, *stat.Dislike, *stat.View, *stat.Coin,
  57. *stat.Favorite, *stat.Reply, *stat.Share, *stat.Like, *stat.Dislike, *stat.View, *stat.Coin)
  58. if err != nil {
  59. log.Error("Update(%d,%+v) error(%+v)", stat.Aid, stat, err)
  60. PromError("db:更新计数")
  61. return
  62. }
  63. rows, err = res.RowsAffected()
  64. return
  65. }
  66. // UpdateSearch update search article table
  67. func (d *Dao) UpdateSearch(c context.Context, a *model.SearchArticle) (err error) {
  68. _, err = d.updateSearchStmt.Exec(c, a.CTime, a.ID, a.CategoryID, a.Title, a.Summary, a.TemplateID, a.Mid, a.ImageURLs, a.PublishTime, a.Content, a.Tags, a.StatsView, a.StatsFavorite, a.StatsLikes, a.StatsDisLike, a.StatsReply, a.StatsShare, a.StatsCoin, a.OriginImageURLs, a.Attributes, a.Keywords,
  69. a.CTime, a.CategoryID, a.Title, a.Summary, a.TemplateID, a.Mid, a.ImageURLs, a.PublishTime, a.Content, a.Tags, a.StatsView, a.StatsFavorite, a.StatsLikes, a.StatsDisLike, a.StatsReply, a.StatsShare, a.StatsCoin, a.OriginImageURLs, a.Attributes, a.Keywords)
  70. if err != nil {
  71. PromError("db:更新搜索表")
  72. log.Error("UpdateSearch(%+v) error(%+v)", a, err)
  73. }
  74. return
  75. }
  76. // DelSearch del search article table
  77. func (d *Dao) DelSearch(c context.Context, aid int64) (err error) {
  78. _, err = d.delSearchStmt.Exec(c, aid)
  79. if err != nil {
  80. PromError("db:删除搜索表")
  81. log.Error("DelSearch(%v) error(%+v)", aid, err)
  82. return
  83. }
  84. return
  85. }
  86. // UpdateRecheck update recheck table
  87. func (d *Dao) UpdateRecheck(c context.Context, aid int64) (err error) {
  88. _, err = d.updateRecheckStmt.Exec(c, aid)
  89. if err != nil {
  90. PromError("db:修改回查状态")
  91. log.Error("UpdateRecheck(%v) error(%+v)", aid, err)
  92. }
  93. return
  94. }
  95. // ArticleContent get article content
  96. func (d *Dao) ArticleContent(c context.Context, id int64) (res string, err error) {
  97. contentSQL := fmt.Sprintf(_articleContentSQL, d.hit(id))
  98. if err = d.db.QueryRow(c, contentSQL, id).Scan(&res); err != nil {
  99. if err == sql.ErrNoRows {
  100. err = nil
  101. return
  102. }
  103. PromError("db:ArticleContent")
  104. log.Error("dao.ArticleContent(%s) error(%+v)", contentSQL, err)
  105. }
  106. return
  107. }
  108. // GetRecheckInfo get article recheck
  109. func (d *Dao) GetRecheckInfo(c context.Context, id int64) (publishTime int64, checkState int, err error) {
  110. if err = d.getRecheckStmt.QueryRow(c, id).Scan(&publishTime, &checkState); err != nil {
  111. if err == sql.ErrNoRows {
  112. err = nil
  113. return
  114. }
  115. PromError("db:ReCheckQuery")
  116. log.Error("dao.GetRecheckInfo(%d) error(%+v)", id, err)
  117. }
  118. return
  119. }
  120. // UpdateSearchStats update search stats
  121. func (d *Dao) UpdateSearchStats(c context.Context, stat *artmdl.StatMsg) (err error) {
  122. _, err = d.updateSearchStatsStmt.Exec(c, *stat.View, *stat.Favorite, *stat.Like, *stat.Dislike, *stat.Reply, *stat.Share, *stat.Coin, stat.Aid)
  123. if err != nil {
  124. log.Error("updateSearchStatsStmt(%d,%+v) error(%+v)", stat.Aid, stat, err)
  125. PromError("db:更新搜索计数")
  126. }
  127. return
  128. }
  129. // RawGameList game list
  130. func (d *Dao) RawGameList(c context.Context) (mids []int64, err error) {
  131. rows, err := d.gameStmt.Query(c)
  132. if err != nil {
  133. return
  134. }
  135. defer rows.Close()
  136. for rows.Next() {
  137. var id int64
  138. if rows.Scan(&id); err != nil {
  139. PromError("db:GameList")
  140. log.Error("dao.GameList() error(%+v)", err)
  141. return
  142. }
  143. mids = append(mids, id)
  144. }
  145. return
  146. }
  147. // CheatArts cheat list
  148. func (d *Dao) CheatArts(c context.Context) (res map[int64]int, err error) {
  149. rows, err := d.cheatStmt.Query(c)
  150. if err != nil {
  151. return
  152. }
  153. res = make(map[int64]int)
  154. defer rows.Close()
  155. defer func() {
  156. if err != nil {
  157. PromError("db:CheatArts")
  158. log.Error("dao.CheatArts() error(%+v)", err)
  159. }
  160. }()
  161. for rows.Next() {
  162. var id int64
  163. var lv int
  164. if rows.Scan(&id, &lv); err != nil {
  165. return
  166. }
  167. res[id] = lv
  168. }
  169. err = rows.Err()
  170. return
  171. }
  172. // NewestArtIDs find newest article's id
  173. func (d *Dao) NewestArtIDs(c context.Context, limit int64) (res [][2]int64, err error) {
  174. rows, err := d.newestArtsMetaStmt.Query(c, limit)
  175. if err != nil {
  176. PromError("db:最新文章")
  177. log.Error("dao.newestArtsMetaStmt.Query error(%+v)", err)
  178. return
  179. }
  180. defer rows.Close()
  181. for rows.Next() {
  182. var (
  183. id int64
  184. ptime int64
  185. attribute int32
  186. )
  187. if err = rows.Scan(&id, &ptime, &attribute); err != nil {
  188. PromError("db:最新文章scan")
  189. log.Error("dao.NewestArtIDs.rows.Scan error(%+v)", err)
  190. return
  191. }
  192. if artmdl.NoDistributeAttr(attribute) || artmdl.NoRegionAttr(attribute) {
  193. continue
  194. }
  195. res = append(res, [2]int64{id, ptime})
  196. }
  197. if err = rows.Err(); err != nil {
  198. PromError("db:最新文章")
  199. log.Error("dao.NewestArtIDs.rows error(%+v)", err)
  200. }
  201. return
  202. }
  203. // NewestArtIDByCategory find newest article's id
  204. func (d *Dao) NewestArtIDByCategory(c context.Context, cids []int64, limit int64) (res [][2]int64, err error) {
  205. sql := fmt.Sprintf(_newestArtCategorysMetaSQL, xstr.JoinInts(cids), limit)
  206. rows, err := d.db.Query(c, sql)
  207. if err != nil {
  208. PromError("db:最新文章")
  209. log.Error("dao.NewestArtIDByCategorys.Query error(%+v)", err)
  210. return
  211. }
  212. defer rows.Close()
  213. for rows.Next() {
  214. var (
  215. id int64
  216. ptime int64
  217. attribute int32
  218. )
  219. if err = rows.Scan(&id, &ptime, &attribute); err != nil {
  220. PromError("db:最新文章scan")
  221. log.Error("dao.NewestArtIDByCategory.rows.Scan error(%+v)", err)
  222. return
  223. }
  224. if artmdl.NoDistributeAttr(attribute) || artmdl.NoRegionAttr(attribute) {
  225. continue
  226. }
  227. res = append(res, [2]int64{id, ptime})
  228. }
  229. if err = rows.Err(); err != nil {
  230. PromError("db:最新文章")
  231. log.Error("dao.NewestArtIDByCategory.Scan error(%+v)", err)
  232. }
  233. return
  234. }
  235. // SearchArts get articles publish time after ptime
  236. func (d *Dao) SearchArts(c context.Context, ptime int64) (res []*model.SearchArticle, err error) {
  237. var rows *sql.Rows
  238. now := time.Now().Unix()
  239. for ; ptime < now; ptime += _searchInterval {
  240. if rows, err = d.searchArtsStmt.Query(c, ptime, ptime+_searchInterval); err != nil {
  241. PromError("db:searchArts")
  242. log.Error("mysql: search arts Query() error(%+v)", err)
  243. return
  244. }
  245. defer rows.Close()
  246. for rows.Next() {
  247. ba := &model.SearchArticle{}
  248. if err = rows.Scan(&ba.ID, &ba.CategoryID, &ba.Attributes, &ba.StatsView, &ba.StatsReply, &ba.StatsFavorite, &ba.StatsLikes, &ba.StatsCoin); err != nil {
  249. PromError("db:searchArts")
  250. log.Error("mysql: search arts Scan() error(%+v)", err)
  251. return
  252. }
  253. res = append(res, ba)
  254. }
  255. if err = rows.Err(); err != nil {
  256. PromError("db:searchArts")
  257. log.Error("mysql: search arts Query() error(%+v)", err)
  258. return
  259. }
  260. }
  261. return
  262. }
  263. // Settings gets article settings.
  264. func (d *Dao) Settings(c context.Context) (res map[string]string, err error) {
  265. var rows *sql.Rows
  266. if rows, err = d.settingsStmt.Query(c); err != nil {
  267. PromError("db:文章配置查询")
  268. log.Error("mysql: db.settingsStmt.Query error(%+v)", err)
  269. return
  270. }
  271. defer rows.Close()
  272. res = make(map[string]string)
  273. for rows.Next() {
  274. var name, value string
  275. if err = rows.Scan(&name, &value); err != nil {
  276. PromError("文章配置scan")
  277. log.Error("mysql: rows.Scan error(%+v)", err)
  278. return
  279. }
  280. res[name] = value
  281. }
  282. err = rows.Err()
  283. if err = rows.Err(); err != nil {
  284. PromError("db:loadSettings")
  285. log.Error("mysql: load settings Query() error(%+v)", err)
  286. }
  287. return
  288. }
  289. //MidsByPublishTime get mids by publish time
  290. func (d *Dao) MidsByPublishTime(c context.Context, pubTime int64) (mids []int64, err error) {
  291. var rows *sql.Rows
  292. if rows, err = d.midByPubtimeStmt.Query(c, pubTime); err != nil {
  293. PromError("db:查询近7天mid")
  294. log.Error("mysql: db.MidsByPublishTime.Query error(%+v)", err)
  295. return
  296. }
  297. defer rows.Close()
  298. for rows.Next() {
  299. var mid int64
  300. if err = rows.Scan(&mid); err != nil {
  301. PromError("查询近7天mid scan")
  302. log.Error("mysql: rows.Scan error(%+v)", err)
  303. return
  304. }
  305. mids = append(mids, mid)
  306. }
  307. err = rows.Err()
  308. if err = rows.Err(); err != nil {
  309. PromError("db:MidsByPublishTime")
  310. log.Error("mysql: get mids by publish time Query() error(%+v)", err)
  311. }
  312. return
  313. }
  314. //StatByMid get author info by mid
  315. func (d *Dao) StatByMid(c context.Context, mid int64) (res map[int64][2]int64, err error) {
  316. res = make(map[int64][2]int64)
  317. var rows *sql.Rows
  318. if rows, err = d.statByMidStmt.Query(c, mid); err != nil {
  319. PromError("db:作者分区数据")
  320. log.Error("mysql: db.statByMidStmt.Query error(%+v)", err)
  321. return
  322. }
  323. defer rows.Close()
  324. for rows.Next() {
  325. var (
  326. data [2]int64
  327. cate int64
  328. )
  329. if err = rows.Scan(&data[0], &data[1], &cate); err != nil {
  330. PromError("作者分区数据 scan")
  331. log.Error("mysql: rows.Scan error(%+v)", err)
  332. return
  333. }
  334. res[cate] = data
  335. }
  336. err = rows.Err()
  337. if err = rows.Err(); err != nil {
  338. PromError("db:StatByMid")
  339. log.Error("mysql: get stat infos by mid Query() error(%+v)", err)
  340. }
  341. return
  342. }
  343. // Keywords .
  344. func (d *Dao) Keywords(c context.Context, id int64) (keywords string, err error) {
  345. var sqlStr = fmt.Sprintf(_keywordsSQL, d.hit(id))
  346. row := d.db.QueryRow(c, sqlStr, id)
  347. if err = row.Scan(&keywords); err != nil {
  348. PromError("db:Keywords")
  349. log.Error("d.keywords scan error(%+v)", err)
  350. }
  351. return
  352. }
  353. // IsAct .
  354. func (d *Dao) IsAct(c context.Context, id int64) (res bool) {
  355. var actID int64
  356. if err := d.db.QueryRow(c, _actIDSQL, id).Scan(&actID); err != nil {
  357. PromError("db:IsAct")
  358. log.Error("d.IsAct scan error(%+v)", err)
  359. return
  360. }
  361. if actID > 0 {
  362. res = true
  363. }
  364. return
  365. }
  366. // LastModIDs .
  367. func (d *Dao) LastModIDs(c context.Context, size int) (aids []int64, err error) {
  368. var (
  369. id int64
  370. rows *sql.Rows
  371. )
  372. if rows, err = d.db.Query(c, _lastModsArtsSQL, size); err != nil {
  373. PromError("db:LastModIDs")
  374. log.Error("d.LastModIDs query error(%+v) size(%d)", err, size)
  375. return
  376. }
  377. for rows.Next() {
  378. if err = rows.Scan(&id); err != nil {
  379. PromError("db:LastModIDs")
  380. log.Error("d.LastModIDs scan error(%+v) size(%d)", err, size)
  381. return
  382. }
  383. aids = append(aids, id)
  384. }
  385. return
  386. }