gpt4 book ai didi

php - 与 NoSQL 数据库相关

转载 作者:IT老高 更新时间:2023-10-28 13:37:22 25 4
gpt4 key购买 nike

这个问题是针对所有 NoSQL 和特别是 mongoDB 专家的。我开始为一个项目设计一个关系数据库,但客户希望我们使用可以轻松扩展的数据库。为了实现这一点,我们决定使用 mongoDB。这些天来,我在为 NoSQL 映射关系模型时遇到了麻烦。我有一个用户表,它与许多其他表具有多对多关系,如下所示:

relational DB

在将其转换为 mongoDB 时,我有几个选项:

选项 1(用户中有完整的行):

users:{
_id:<user_id>,
battles:{[battle1, battle2, ...]},
items:{[item1, item2, ...]},
locations:{[location1, location2, ...]},
units:{[unit1, unit2, ...]},
}

battles:{
<battle_info>
}

locations:{
<location_info>
}

units:{
<units_info>
}

items:{
<items_info>
}

选项2(用户中只有外键):

users:{
_id:<user_id>,
battles:{[battle1_id, battle2_id, ...]},
items:{[item1_id, item2_id, ...]},
locations:{[location1_id, location2_id, ...]},
units:{[unit1_id, unit2_id, ...]},
}

battles:{
<battle_info>
}

locations:{
<location_info>
}

units:{
<units_info>
}

items:{
<items_info>
}

选项 3(其他表中的用户 ID):

users:{
_id:<user_id>,
}

battles:{
<battle_info>,
user:{[user1_id, user2_id, ...]}
}

locations:{
<location_info>,
user:{[user1_id, user2_id, ...]}
}

units:{
<units_info>,
user:{[user1_id, user2_id, ...]}
}

items:{
<items_info>,
user:{[user1_id, user2_id, ...]}
}

选项 1 有很多重复,因为我们要添加其他表的完整行。我在其中看到的一个问题是,如果某个项目或战斗被更新,我们将不得不在用户表中找到它的所有出现并更新它们。但这给了我们一个优势,即始终拥有一个完整的用户对象,该对象可以在登录时交给客户端应用程序。

选项 2 更具相关性,我们在 users 表中只有其他表的 mongoId。此选项的优点是更新战斗或元素不会有太多成本,因为行被引用而不是复制。另一方面,当用户登录时,我们必须找到所有引用的单位、战斗、元素和位置,以使用完整的用户对象进行响应。

选项3与选项2相反,其中用户表的mongoIds保存在其他表中。这个选项对我没有多大吸引力。

如果有人可以指导我或提出更好的模型,我将不胜感激。

编辑:

基本上这是一个多人游戏,其中多个客户端应用程序将通过网络服务连接到服务器。我们在客户端有一个本地数据库来存储数据。我想要一个模型,服务器可以通过该模型以完整的用户对象进行响应,然后更新或插入客户端应用程序上更改的数据。

最佳答案

首先,NoSQL 不是一刀切。在 SQL 中,几乎每个 1:N 和 M:N 关系都以相同的方式建模。 NoSQL 的理念是,对数据建模的方式取决于数据及其使用模式。

其次,我同意 Mark Ba​​ker 的观点:扩展很难,它是通过放松约束来实现的。这不是技术问题。我喜欢使用 MongoDB,但出于其他原因(不需要编写丑陋的 SQL;不需要复杂、臃肿的 ORM;等等)

现在让我们回顾一下您的选择:选项 1 复制的数据比需要的多。您经常需要对 一些 数据进行非规范化,但绝不是全部。如果是这样,获取引用的对象会更便宜。

选项 2/3 它们非常相似。这里的关键是:谁在写?您不希望很多客户端对同一个文档具有写访问权限,因为这将迫使您使用锁定机制,和/或将自己限制为仅修改操作。因此,选项 2 可能比 3 更好。但是,如果 A 攻击 B,它们也会触发对用户 B 的写入,因此您必须确保您的写入是安全的。

选项 4 部分非规范化:您的用户对象似乎是最重要的,那么如何:

user { 
battles : [ {"Name" : "The battle of foo", "Id" : 4354 }, ... ]
...
}

这将使显示更容易,例如用户仪表板,因为您不需要了解仪表板中的所有详细信息。注意:数据结构随后会与演示的细节相结合。

选项 5 边缘数据。通常,关系也需要保存数据:

user {
battles : [ {"Name" : "The battle of foo", "unitsLost" : 54, "Id" : 34354 }, ... ]
}

这里,unitsLost 是特定于用户和战斗的,因此数据位于图表的边缘。与战斗名称相反,此数据未进行非规范化。

选项 6 链接器集合。当然,这样的“边缘数据”可能会变得巨大,甚至可能需要一个单独的集合(链接器集合)。这完全消除了访问锁的问题:

user { 
"_id" : 3443
}

userBattles {
userId : 3443,
battleId : 4354,
unitsLost : 43,
itemsWon : [ <some list > ],
// much more data
}

哪些是最好的取决于您的应用程序的许多细节。如果用户进行了很多点击(即你有一个细粒度的界面),那么像选项 4 或 6 那样拆分对象是有意义的。如果你真的需要一批中的所有数据,部分非规范化没有帮助,所以备选方案 2 更可取。请记住多作者问题。

关于php - 与 NoSQL 数据库相关,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8849571/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com