最近在做毕设,遇到一个数据库存储的问题,不知该如何选择,请各位指点一二。
(楼主是一个前端,后端和数据库很多地方不太懂,如果有的地方说的不对,还请大家批评)
与发微博这个操作类似,我就以发微博来说。
一条微博包括内容
和多张图片
。
数据库里,内容
就是一个字段,而微博-图片是一个一对多的关系。
在发微博上传图片的时候,我实现的流程是:
一个例子:
POST /user/xxxx/status
data:
{
"content" : "微博内容",
"pics" : [
"picId-1",
"picId-2",
"picId-3"
],
}
而且,图片还是有顺序的。
到正题了,后端该如何存储这条微博。
下面是我想到的几种方案
图片信息表结构:
微博表:
微博-图片表:
微博表
比如:
pics = "picId1,picId2,picId3"
比如:
pics = [picId1,picId2,picId3]
暂时就想到这几种方案。
请问各位这几种方案孰优孰劣,选择哪种更好一点?
还有没有更好的方案选择呢?
1
zhengjian OP |
2
zhengjian OP 睡觉前又想到一个方案。
图片表增加一个 status_id 字段,上传图片的时候为 null,当发布微博的时候再将微博 id 插入进去。 顺序问题还要想想。 |
3
2kCS5c0b0ITXE5k2 2019-05-03 05:15:18 +08:00
@zhengjian 顺序问题可以加一个字段 按照上传顺序 比如你上传第一张 Post 的时候加一个标识为第几张
|
4
2kCS5c0b0ITXE5k2 2019-05-03 05:19:05 +08:00
@zhengjian 实现起来当然 2.2 更好。但是后续升级维护还是第一种更好
|
5
zhengjian OP |
6
GoLand 2019-05-03 06:07:08 +08:00 via iPhone
用 2.2。图片 ident 塞到信息序列化成字符串,可以前面加个 key。比如 { “ pics ”:[xx, xx]}。之后加其他额外信息往这个 map 里加就行了。好扩展。对于你的第一种方案,画蛇添足,因为图片一般没有查询场景吧?
|
7
kevinlm 2019-05-03 06:30:00 +08:00 via iPhone
图片地址存成一个字段,完事,地址本来就是唯一的。
|
8
richard1122 2019-05-03 09:59:11 +08:00
图片应该很大概率是不需要单独查找的吧,用 方案 2。
|
9
richard1122 2019-05-03 10:00:19 +08:00
另外应该用 json 方式,以后万一有特别的需求 mysql 还可以用 json 操作函数计算
|
10
DavidNineRoc 2019-05-03 10:09:26 +08:00
说说方案吧:
json 存储: (图片表) 优势显然可见, 简单. 还有你的问题不会存在, 解析字符串再查询? 有想会查询图片呢? 解析的话, 这个无所谓, 像 redis 缓存一样是把整个数据缓存成字符串. 一对多: (微博表, 图片表) 你的更多可能是一对多, 步骤应该是这样. 前端选择图片,上传之后, 切记不要插入数据库. 因为如果你现在插入, 如果我刷新, 或者不发表文章了, 你的数据库记录是删除掉?反而麻烦了自己. 正确做法: 前端选择图片 -> 云存储(本地存储)保存返回 url 数组 -> 前端直接根据 url 预览 -> 写微博点击发表 -> 先创建微博 -> 拿微博 id 新建图片表 多对多: (微博表, 图片表, 关联表) 这种表结构一定要确定好你的应用场景, 建议和一对多区分开. 这种做法常见的可以参考 wordpress, 一般有一个媒体库. 发微博之前一般先去媒体库上传图片, 等你去微博的时候, 可以选择之前上传过的所有图片(当然你也可以在新建微博的时候上传图片, 同理这些图片在以后也可以继续使用) |
11
kangzai50136 2019-05-03 13:21:24 +08:00 via Android
我最近也在做差不多的功能,我是用微博表,微博详情表和图片表。虽然表多,但结构清晰。
|
12
xuanbg 2019-05-03 13:55:39 +08:00
图片又不搜索,当然存成 json 最简单。MySQL5.6 就有 json 的支持了,哪怕更早版本,直接当做字符串存储也没问题,反正你并不需要在 sql 语句中解析。
|
13
zhengjian OP @kangzai50136 #11 请问您的需求中需要保存顺序吗,是怎么解决顺序问题的呢?
@DavidNineRoc #10 感谢您的耐心解答,对于你第二点中的解释,“前端选择图片 -> 云存储(本地存储)保存返回 url 数组”,在返回 url 数组的时候,因为图片会有其他信息和多个 url,这时后端是不是要设置一个过期时间缓存一下,当微博发送的时候再插入数据库,如果用户不发表了,这些图也就过期了。 |
14
kangzai50136 2019-05-03 18:57:41 +08:00 via Android
@zhengjian 我是增加一个排序字段,排序由前端决定,接口接收参数时检验一下排序字段有没有重复,有则返回错误。{“ content ”:“我是一条新微博”,pics[{filename:xx,sort:1},{filename:yyy,sort:2}]},有兴趣可以加我企鹅大家讨论一下。
|
15
zhengwhizz 2019-05-03 21:07:48 +08:00 via Android
图片直接前端预览 /压缩( pica),发微博时才上传,避免用户取消发布、删除 /修改图片再请求接口(或者无用图片的存储,毕设可以忽略,产品的话这种操作不在少数, 云存储带宽和容量这些都是成本),至于多表或者 json 没太大区别,个人觉得 json 更方便,至于排序,加个修改时间戳,前端排一下即可。
|
16
zhengjian OP @kangzai50136 #14 那您修改图片顺序的时候,操作量不会很大。
@zhengwhizz #15 嗯嗯,一起上传的话,如果九张图,考虑到速度问题,还是选择了先上传图片。因为实际需求比微博的表单字段要多很多。 |
17
kangzai50136 2019-05-03 23:18:38 +08:00 via Android
@zhengjian 为什么修改图片顺序操作量会很大呢
|
18
zhengjian OP |
19
autogen 2019-05-04 00:34:15 +08:00
一般都是这样设计的:
微博表: - weibo_id * - content 图片表: - pic_id - width - height - thumb - origin - weibo_id * 而且图片服务器会返回一个图片 ID,根据这个 ID 来拼链接就行 比如:图片 ID=aaaabbbbccccdddd, url 你自己拼就行: http://cdn1.cdn.com/aaaabbbbccccdddd_100x100.jpg - |
20
autogen 2019-05-04 00:41:52 +08:00
代码:
def getWeiboInfo(id): ....getBaseInfo(id) ....getImgInfo(id) ....return combine(base, imgs); - def getBaseInfo(id): ....if id in cache: ........return cache.get(id) ....return weibo.query(id) - |
21
autogen 2019-05-04 00:43:55 +08:00
图片顺序,图片表加个 order 字段
|
22
zhengjian OP @autogen #21 感谢详细讲解。这样的话是标准的一对多关系。当上传来图片的时候在图片表插入一条记录,weibo_id , order 设为 null,发布微博的时候再批量修改这几条图片记录的 weibo_id 和 order。新发布的时候逻辑很清晰。
当修改的时候,对比当前图片数组与新的图片数组,需要分几种情况: 1. 顺序变,更改 order 2. 有增加,将 weibo_id 插入增加的那张图片的记录,并重新修改 order 3. 有删除,将删除的图片那条记录 weibo_id 设为 null 或删除这条记录,并重新修改 order 这样修改的时候,操作会比较复杂一点。 希望我没理解错误。 |