PostgreSQL 模式结构
PostgreSQL schema structuring
这个问题可能太宽泛了,但我正在构建一个博客应用程序 (Express/React/Postgres),而且我是后端领域的新手。
我有 users
和 posts
的 table,如果我想跟踪用户反应(点赞、微笑、大笑等),您可以在帖子中这样做吗table 或创建一个新的 reactions
table,fkey 引用 users.id 和 posts.id?
我问是因为我做了后者,然后意识到帖子可以有多个用户和反应,所以我不确定这样做的正确/最佳方法,即使使用 JOIN。
如果是 JSON,这就是我的想法,但我不知道如何将其转换为 SQL tables 和 knex 查询。
[
{
"posts": [
{
"post_id": "1234567890ABCDEF",
"content": "foo bar",
"created_at": "01/18/2020",
"reactions": {
"users": [
{
"user_id": "D237NH23DGU6",
"reaction": "thumbsup"
},
{
"user_id": "DVSY8N8VSDYN6",
"reaction": "angry"
},
{
"user_id": "3D2J892D3J8933",
"reaction": "laughing"
},
{
"user_id": "23987DNHIUO8DD",
"reaction": "thumbsup"
}
]
}
},
{
"post_id": "99FJ48FJ4F8JHSH",
"content": "bar foo",
"created_at": "01/18/2020",
"reactions": {
"users": [
{
"user_id": "DSDF879344FH97",
"reaction": "sad"
},
{
"user_id": "8S7DF62HF87H34F",
"reaction": "peace"
},
{
"user_id": "37HHF783H4K47834",
"reaction": "laughing"
}
]
}
},
{
"post_id": "1234567890ABCDEF",
"content": "foo foo bar bar",
"created_at": "01/18/2020",
"reactions": {
"users": [
{
"user_id": "SDFWEF934949J4",
"reaction": "thumbsup"
},
{
"user_id": "R9TVU8TRVU89",
"reaction": "angry"
},
{
"user_id": "IJFG0F8GJ9",
"reaction": "laughing"
},
{
"user_id": "3F4V3NHVF43N8",
"reaction": "thumbsup"
},
{
"user_id": "VXDRTHVHM6D7",
"reaction": "angry"
},
{
"user_id": "A9SFDHSFDH78",
"reaction": "laughing"
},
{
"user_id": "DFSM8H87M9N",
"reaction": "thumbsup"
}
]
}
}
]
}
]
是的,反应 table 指的是 post 用户,他们的反应是正确的。
knex.schema.createTable('post_reactions', function(t) {
t.integer('user').notNullable();
t.foreign('user').references('id').inTable('users');
t.integer('post').notNullable();
t.foreign('post').references('id').inTable('posts');
t.string('reaction').notNullable();
t.unique(['user', 'post', 'reaction']);
}
独特之处在于,每个 post 用户只能做出一次特定反应。
获取对 post 3 的反应不需要连接。
knex('post_reactions')
.select('user', 'reaction')
.where('post', 3)
但也许您需要用户名和 post 的标题。
knex('post_reactions')
.join('users', 'users.id', '=', 'post_reactions.user')
.join('posts', 'posts.id', '=', 'post_reactions.post')
.select('posts.title', 'users.name', 'reaction')
.where('post', 3)
我做到了 post_reactions
既是因为它们是对 post 的反应(为对其他事物的反应留有余地),也是因为您可能想为所有人做出 table可能的反应并加入其中。
knex.schema.createTable('reactions', function(t) {
t.increments();
t.string('keyword').notNullable();
t.unique('keyword');
}
knex.schema.createTable('post_reactions', function(t) {
t.integer('user').notNullable();
t.foreign('user').references('id').inTable('users');
t.integer('post').notNullable();
t.foreign('post').references('id').inTable('posts');
t.integer('reaction').notNullable();
t.foreign('reaction').references('id').inTable('reactions');
t.unique(['user', 'post', 'reaction']);
}
如果除了 post 的标题和用户名之外还需要反应关键字,现在我们需要一个额外的连接。
knex('post_reactions')
.join('users', 'users.id', '=', 'post_reactions.user')
.join('posts', 'posts.id', '=', 'post_reactions.post')
.join('reactions', 'reactions.id', '=', 'post_reactions.reaction')
.select('posts.title', 'users.name', 'reaction.keyword')
.where('post', 3)
这样做的好处是可以确保 post_reactions
中的每个条目都是真实的反应。错别字是不可能的。这也意味着关键字或其他关于反应的东西可以改变,但反应仍然有效。
请注意,我避免将反应图像本身存储在数据库中。您 可以 这样做,但通常最好将资产存储在磁盘上并引用文件。这允许直接链接到资产,减少数据库的负载,并让人们无需接触数据库即可使用资产。
这个问题可能太宽泛了,但我正在构建一个博客应用程序 (Express/React/Postgres),而且我是后端领域的新手。
我有 users
和 posts
的 table,如果我想跟踪用户反应(点赞、微笑、大笑等),您可以在帖子中这样做吗table 或创建一个新的 reactions
table,fkey 引用 users.id 和 posts.id?
我问是因为我做了后者,然后意识到帖子可以有多个用户和反应,所以我不确定这样做的正确/最佳方法,即使使用 JOIN。
如果是 JSON,这就是我的想法,但我不知道如何将其转换为 SQL tables 和 knex 查询。
[
{
"posts": [
{
"post_id": "1234567890ABCDEF",
"content": "foo bar",
"created_at": "01/18/2020",
"reactions": {
"users": [
{
"user_id": "D237NH23DGU6",
"reaction": "thumbsup"
},
{
"user_id": "DVSY8N8VSDYN6",
"reaction": "angry"
},
{
"user_id": "3D2J892D3J8933",
"reaction": "laughing"
},
{
"user_id": "23987DNHIUO8DD",
"reaction": "thumbsup"
}
]
}
},
{
"post_id": "99FJ48FJ4F8JHSH",
"content": "bar foo",
"created_at": "01/18/2020",
"reactions": {
"users": [
{
"user_id": "DSDF879344FH97",
"reaction": "sad"
},
{
"user_id": "8S7DF62HF87H34F",
"reaction": "peace"
},
{
"user_id": "37HHF783H4K47834",
"reaction": "laughing"
}
]
}
},
{
"post_id": "1234567890ABCDEF",
"content": "foo foo bar bar",
"created_at": "01/18/2020",
"reactions": {
"users": [
{
"user_id": "SDFWEF934949J4",
"reaction": "thumbsup"
},
{
"user_id": "R9TVU8TRVU89",
"reaction": "angry"
},
{
"user_id": "IJFG0F8GJ9",
"reaction": "laughing"
},
{
"user_id": "3F4V3NHVF43N8",
"reaction": "thumbsup"
},
{
"user_id": "VXDRTHVHM6D7",
"reaction": "angry"
},
{
"user_id": "A9SFDHSFDH78",
"reaction": "laughing"
},
{
"user_id": "DFSM8H87M9N",
"reaction": "thumbsup"
}
]
}
}
]
}
]
是的,反应 table 指的是 post 用户,他们的反应是正确的。
knex.schema.createTable('post_reactions', function(t) {
t.integer('user').notNullable();
t.foreign('user').references('id').inTable('users');
t.integer('post').notNullable();
t.foreign('post').references('id').inTable('posts');
t.string('reaction').notNullable();
t.unique(['user', 'post', 'reaction']);
}
独特之处在于,每个 post 用户只能做出一次特定反应。
获取对 post 3 的反应不需要连接。
knex('post_reactions')
.select('user', 'reaction')
.where('post', 3)
但也许您需要用户名和 post 的标题。
knex('post_reactions')
.join('users', 'users.id', '=', 'post_reactions.user')
.join('posts', 'posts.id', '=', 'post_reactions.post')
.select('posts.title', 'users.name', 'reaction')
.where('post', 3)
我做到了 post_reactions
既是因为它们是对 post 的反应(为对其他事物的反应留有余地),也是因为您可能想为所有人做出 table可能的反应并加入其中。
knex.schema.createTable('reactions', function(t) {
t.increments();
t.string('keyword').notNullable();
t.unique('keyword');
}
knex.schema.createTable('post_reactions', function(t) {
t.integer('user').notNullable();
t.foreign('user').references('id').inTable('users');
t.integer('post').notNullable();
t.foreign('post').references('id').inTable('posts');
t.integer('reaction').notNullable();
t.foreign('reaction').references('id').inTable('reactions');
t.unique(['user', 'post', 'reaction']);
}
如果除了 post 的标题和用户名之外还需要反应关键字,现在我们需要一个额外的连接。
knex('post_reactions')
.join('users', 'users.id', '=', 'post_reactions.user')
.join('posts', 'posts.id', '=', 'post_reactions.post')
.join('reactions', 'reactions.id', '=', 'post_reactions.reaction')
.select('posts.title', 'users.name', 'reaction.keyword')
.where('post', 3)
这样做的好处是可以确保 post_reactions
中的每个条目都是真实的反应。错别字是不可能的。这也意味着关键字或其他关于反应的东西可以改变,但反应仍然有效。
请注意,我避免将反应图像本身存储在数据库中。您 可以 这样做,但通常最好将资产存储在磁盘上并引用文件。这允许直接链接到资产,减少数据库的负载,并让人们无需接触数据库即可使用资产。