哪个更糟?多一个数据库访问权限还是一个过时的值?
Posted
技术标签:
【中文标题】哪个更糟?多一个数据库访问权限还是一个过时的值?【英文标题】:Which is worse? One more db acess or one outdated value? 【发布时间】:2015-11-30 01:51:27 【问题描述】:问题
我正在使用 AngularJS、Node JS、Express 和 MongoDB 运行应用程序。我正在访问 MongoDB trought mongoose。我的问题是我有一个剑的清单,每一个都是有人伪造的。但是,要访问某人的个人资料,我需要使用某人的 ID。 ID 是唯一的。但我无法将链接显示为链接“352384b685326vyad6”。所以,当有人创造了一把剑时,我会将他或她的名字存储在剑信息中。
例如,要显示剑列表,我可以这样做:
<div ng-repeat='sword in swords'>
<p> Sword name: sword.name </p>
<p> Author: <a href='#/user/sword.createdByID'> sword.createdByName </a> </p>
</div>
但是,如果用户更改了他的名字,剑不会相应地更新他的创建者名字。我该怎么办?我已经想到了一些解决方案,但我不知道哪个以及是否可以很好地解决这个问题。
当有人更改自己的名字时,我可以使用新的用户名和 ID 发出 POST 请求,更新所有 createdByID 等于用户 ID 的剑。但我觉得这太奇怪了。
SwordModel.find( createdByID: req.body.id, [...]);
当通过 GET 请求在控制器中加载剑时,为每个剑发出另一个 GET 请求并根据剑.createdById 更新剑.用户名。
UserModel.findById(req.body.id), [...]);
忘记用户体验并使用丑陋的链接。
我想知道如何在不影响数据库的情况下更新每把剑的用户名。谢谢您的建议。
模型 - 仅供参考。
剑.js
var mongoose = require('mongoose');
var SwordModel = mongoose.model('SwordModel',
name: String, //Sword's name
createdById: String, //ID of the user who created.
createdByName: String //Name of the user
);
module.exports = mongoose.model('SwordModel', SwordModel);
user.js
var mongoose = require('mongoose');
var UserModel = mongoose.model('UserModel',
name: String, //Name of the user.
ID: String //ID of the user.
);
module.exports = mongoose.model('UserModel', UserModel);
【问题讨论】:
【参考方案1】:如果您使用 Mongoose 模式,您可以通过在 Swords 中引用用户来实现。
引用另一个架构后,您可以使用populate
方法来获得所需的结果。
示例(可能不完全正确,但类似于以下内容):
剑图:
var swordSchema = new Schema(
name: String,
createdBy: type: mongoose.Schema.Types.ObjectId, ref: 'User'
);
使用模式制作模型:
var swordModel = mongoose.model('Sword', swordSchema);
使用填充查找您要查找的内容。
在此处查看完整的填充文档 - http://mongoosejs.com/docs/populate.html
编辑:请注意,我建议仅在用户模型中保留用户名并仅引用它。
【讨论】:
谢谢。您已经展示了一种方法,最重要的是,它向我展示了我真的需要更多地研究 MongoDB,因为我不知道这种填充方法。谢谢。【参考方案2】:我认为这里的技术问题较少,概念问题较多。
约束
我认为这是理所当然的......
用户可以更改他们的用户名 用户名是唯一的 您只需要提供一个指向用户的链接,按名称显示此外,我将使用纯 JSON 和 MongoDB,并相信您可以将其转换为 Mongoose。
解决办法
尽管用户可以更改他们的用户名,但这不会经常发生。更常见的用例是您需要链接到用户名。因此,我们首先需要找出如何有效地处理该用例。
既然你只需要一把给定剑的铁匠的名字,像这样的剑模型没有错
_id: new ObjectId(),
name: "Libertas",
smith: "Foobar"
为了有效地在用户集合中找到“Foobar”,我们只需在此处添加一个索引(如果尚未完成):
db.users.createIndex(username:1, unique:true)
并且您的服务可以通过使用进行高效查询
db.users.find(name: "Foobar")
无需将用户的_id
保存在剑文档中,但仍然可以高效查询。
处理用户名的变化是一个很少执行的用例,所以这里的优化没有意义。但是,如果用户更改了他或她的用户名,您的服务可以轻松地通过
db.swords.update(
smith:"Foobar" ,
$set: smith: "CoolNewUsername" ,
multi: true, writeConcern: w:1, j:true
)
上面的最后一行需要稍微解释一下。 multi: true
选项告诉 MongoDB 更改 所有 匹配 smith: "Foobar"
的文档,而不仅仅是找到的第一个文档,这很容易理解。但是为什么要将写关注设置为journaled?第一个原因是,无论为连接配置的写入关注点(甚至可能是unacknowledged),我们都需要这些更改是持久的。但是,我们通常不需要将更改传播到更多副本集成员,因此选择的写入关注可以为您提供最佳性能,同时您仍然可以确保更改已同步到磁盘。如果您需要更高的持久性,当然可以将写入关注设置为w:2
or w:"majority"
。
优势
-
对于这种关系的最常见用例(显示伪造给定剑的用户的链接),执行此操作所需的所有信息都包含在剑的文档中,以防止可能不必要的查询。
不过,如果用户单击所述链接,则可以有效地查询给定剑的铁匠。
可以更改用户名,并且可以非常高效且持久地实现
缺点
这里的主要缺点是当用户更改他或她的用户名时,您实际上必须修改所有受影响的剑,而使用 Mongoose 引用是不必要的。但是,由于这是一个罕见的用例,并且使用 populate
会导致整个用户文档被加载到只需要用户名的地方,我认为这个缺点可以忽略不计。基本上,您可以将常见用例所需的查询减少一半,而无需手动更新,这种情况很少发生。
我没有看到任何其他缺点。
【讨论】:
感谢您提供详细解释的答案。我将实施您的解决方案。关于用户更改姓名的很少使用的用例的好点。以上是关于哪个更糟?多一个数据库访问权限还是一个过时的值?的主要内容,如果未能解决你的问题,请参考以下文章