哪个更糟?多一个数据库访问权限还是一个过时的值?

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 会导致整个用户文档被加载到只需要用户名的地方,我认为这个缺点可以忽略不计。基本上,您可以将常见用例所需的查询减少一半,而无需手动更新,这种情况很少发生。

我没有看到任何其他缺点。

【讨论】:

感谢您提供详细解释的答案。我将实施您的解决方案。关于用户更改姓名的很少使用的用例的好点。

以上是关于哪个更糟?多一个数据库访问权限还是一个过时的值?的主要内容,如果未能解决你的问题,请参考以下文章

共享文件夹的共享权限和NTFS安全权限有啥区别?哪个权限比较大?用户两个权限都要设置吗?

线程同步和并发

复杂数据权限设计方案

mysql 怎么给单个帐号赋予多个库的访问权限?

我应该在哪个条带事件中更新我的数据库以授予订阅者访问权限

保护用户 PC 上的应用程序数据库访问