我即将构建我的node.js / express / mongoose / 通信应用程序,我正在考虑正确的架构设计用户和帐户。
将有用户从Twitter和Facebook以及本机帐户登录。在稍后阶段,我希望用户将twitter和facebook连接到我的应用程序(可能还有更多外部帐户)。
对于那种情况,我想不出一个好的解决方案。以下是我想到的选项:
1.拥有个人资料模型和帐户模型。配置文件代表唯一用户,而帐户提供用户名和密码(内部帐户)或来自身份验证提供程序(外部帐户)的身份验证数据。个人资料必须至少包含一个嵌套帐户文档。
var ExtAccountSchema = new Schema({
type: String, // eg. twitter, facebook, native
uid: String
});
var IntAccountSchema = new Schema({
username: String,
password: String
});
var ProfileSchema = new Schema({
firstname: String,
lastname: String,
email: String,
accounts: [Account] // Pushing all the accounts in there
});
我不喜欢它的是不同帐户数据导致的帐户文档不一致,以及我在用户登录时难以找到合适的帐户(在嵌套文档中搜索uid和帐户类型).- )
2.将所有数据保存在单个模型
中var ProfileSchema = new Schema({
firstname: String,
lastname: String,
email: String,
twitter-uid: String,
facebook-uid: String
password: String
});
这只是丑陋 - .-找到合适的帐户数据可能更容易/更快,但维护起来并不好。
有更好的解决方案吗? 有最佳做法吗?
答案 0 :(得分:46)
1)您可能需要采取三种策略来构建MongoDB中的数据:
策略(a)是您描述的第一个,其中Profile文档包含一系列Account子文档。
策略(b)类似于策略(a),但您使用一系列对其他文档的引用(通常在Account集合中),而不是嵌入实际文档。
策略(c)是您所描述的“将所有数据都放在一个模型中”。
2)通常认为使用嵌入式文档数组的最佳实践,尤其是当它们中的信息可能不同时。如果它会让您的生活更轻松,您可以使用一个键来区分帐户的类型,如下所示:
{
firstname: 'Fred',
lastname: 'Rogers',
email: 'fred.rogers@example.com',
accounts: [
{ kind: 'facebook',
uid: 'fred.rogers'
},
{ kind: 'internal',
username: 'frogers',
password: '5d41402abc4b2a76b9719d911017c592'
},
{ kind: 'twitter',
uid: 'fredr'
}
]
}
3)MongoDB允许您搜索嵌入的文档。因此,您将编写以下查询(JavaScript语法):
db.profile.find(
{ email: 'fred.rogers@example.com', 'accounts.kind': 'facebook' }
);
使用适当的索引,此查询将非常快。
答案 1 :(得分:0)
我希望它可以帮助像您这样有类似需求的人。
MongoDB中的架构设计和数据建模
SQL具有固定/严格模式,而NoSQL具有动态/灵活模式,即不强制执行文档结构
MongoDB有两种类型的数据模型:
- In referenced or normalized data model, If one document is frequetly refering some data in another document, It would create better data model to embed both documents into one.
- If a single document seems to be large, it is better split your data into referential model, the most frequently-accessed portion of the data should go in the collection that the application loads first
```json
// one person and one address
{
_id: "joe",
name: "Joe Bookreader",
address: {
street: "123 Fake Street",
city: "Faketon",
state: "MA",
zip: "12345"
}
}
```
// one person and his multiple address
{
"_id": "joe",
"name": "Joe Bookreader",
"addresses": [
{
"street": "123 Fake Street",
"city": "Faketon",
"state": "MA",
"zip": "12345"
},
{
"street": "1 Some Other Street",
"city": "Boston",
"state": "MA",
"zip": "12345"
}
]
}
{
_id: 'some string'
name: "O'Reilly Media",
founded: 1980,
location: "CA",
books: [123456789, 234567890, ...]
}
{
_id: 123456789,
title: "MongoDB: The Definitive Guide",
author: [ "Kristina Chodorow", "Mike Dirolf" ],
published_date: ISODate("2010-09-24"),
pages: 216,
language: "English"
}
{
_id: 234567890,
title: "50 Tips and Tricks for MongoDB Developer",
author: "Kristina Chodorow",
published_date: ISODate("2011-05-06"),
pages: 68,
language: "English"
}
_id
信息(即发布者ID)称为publisher_id
。 {
_id: "oreilly",
name: "O'Reilly Media",
founded: 1980,
location: "CA"
}
{
_id: 123456789,
title: "MongoDB: The Definitive Guide",
author: [ "Kristina Chodorow", "Mike Dirolf" ],
published_date: ISODate("2010-09-24"),
pages: 216,
language: "English",
publisher_id: "oreilly"
}
{
_id: 234567890,
title: "50 Tips and Tricks for MongoDB Developer",
author: "Kristina Chodorow",
published_date: ISODate("2011-05-06"),
pages: 68,
language: "English",
publisher_id: "oreilly"
}