Skip to content

书籍下载量统计

简介

需求:记录书籍下载事件及时间,便于统计下载量和书籍热度。是否保存用户级别的下载记录,应结合隐私和数据保留要求决定。

数据库设计与实现

  1. 新增下载记录表,保存书籍、用户和下载时间等字段。

  2. 书籍表增加下载数量汇总字段(如果采用预计算)。

ALTER TABLE `book` ADD `download_count` INT DEFAULT 0;

CREATE TABLE `download_info` (
  `id` int NOT NULL AUTO_INCREMENT,
  `userid` INT NOT NULL,
  `bookid` INT NOT NULL,
  `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

alter table download_info add constraint download_info_user_foreign_key foreign key (userid) references user(id);
alter table download_info add constraint download_info_book_foreign_key foreign key (bookid) references book(id);

后端 API 设计

下载书籍时增加一条下载记录,并更新书籍的下载量汇总字段。下面为逻辑示意,实际实现应校验参数,并根据数据库驱动保证操作的一致性。

// 记录下载事件
const { book_id, user_id } = req.query;

// 下载书籍时,增加一条下载记录
const sql = `insert into download_info (userid, bookid) values(?, ?)`;
await DBHelper(
  sql,
  (err, results) => {
    if (err) {
      logger.error(err);
    res.status(400).send({ error_message: err.message });
      return;
    }
    // 重新计算并更新书籍下载量。生产实现可用事务或原子递增避免并发不一致。
    if (results) {
      const sql = `update book set download_count = (select count(id) from download_info WHERE bookid=?) where id=?;`;
      DBHelper(
        sql,
        (err, results) => {
          if (err) {
            logger.error(err);
            res.status(400).send({ error_message: err.message });
            return;
          }
        },
        [book_id, book_id]
      );
    }
  },
  [user_id, book_id]
);

书籍列表 API 返回新增的 download_count 字段。以下为查询示例:

SELECT id, name, cover_photo, author, brief, price, size, tag, download_count FROM book ORDER BY download_count DESC limit 10;

前端交互设计

界面展示书籍下载数量:

<span>下载 {download_count} 次</span>

代码实现

https://github.com/Novel-Reader/Genshin-novel-reader/pull/81/files

https://github.com/Novel-Reader/Genshin-novel-reader-express-server/pull/27/files

未来

管理员可以查看书籍及下载情况。

统计指定时间范围内下载量最高的书籍。