哪个更糟? 还有一分钱还是一个过时的价值?

问题

我正在用AngularJS,Node JS,Express和MongoDB运行一个应用程序。 我正在接触MongoDB变成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请求,更新已经创build好的所有剑,等于用户ID。 但是我觉得这太奇怪了。

     SwordModel.find({ createdByID: req.body.id}, [...]); 
  • 当通过GET请求在控制器中加载剑时,对每把剑进行另一个GET请求并基于sword.createdById更新sword.username。

     UserModel.findById(req.body.id), [...]); 
  • 忘记用户体验,并使用丑陋的链接。

我想知道如何保持更新每把剑的用户名,而不会影响我的数据库太多感谢您的任何build议。

模型 – 仅供参考。

sword.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); 

我认为我们在这方面的技术问题较less,概念问题较多。

约束

我认为这是理所当然的…

  • 用户可能会更改他们的用户名
  • 用户名是唯一的
  • 你只需要提供一个链接给用户,按名称显示

此外,我将使用普通的JSON和MongoDB,并相信您可以将其转换为Mongoose。

解决scheme

虽然用户可以更改他们的用户名,但这不会经常发生。 更常见的用例是你需要链接到一个用户名。 所以我们首先需要找出如何有效地处理这个用例。

既然你只需要一把剑的名字,剑的模型就没有错

 { _id: new ObjectId(), name: "Libertas", smith: "Foobar" } 

为了在用户集合中有效地find“Foobar”,我们只需在这里添加一个索引(如果还没有完成的话):

 db.users.createIndex({username:1}, {unique:true}) 

并且您的服务可以通过使用来高效查询

 db.users.find({name: "Foobar"}) 

不需要在剑文件中保存用户的_id ,但仍然可以有效地查询它。

处理用户名的变化是一个很less执行的用例,所以在这里优化是没有意义的。 但是,如果用户更改他或她的用户名,您的服务可以很容易地通过

 db.swords.update( { smith:"Foobar" }, { $set:{ smith: "CoolNewUsername" }, { multi: true, writeConcern: { w:1, j:true } ) 

上面的最后一行需要一点解释。 multi: true选项告诉MongoDB更改匹配{smith: "Foobar"} 所有文档,不仅是第一个find的文档,这很容易理解。 但是为什么要把写关注点logging下来呢? 第一个原因是,不pipe为连接configuration的写入关注(甚至可能是未确认的 ),我们都需要这些更改是持久的。 但是,我们通常不需要将更改传播到更多的副本集成员,因此所选的写入关注会为您提供最佳性能,同时您仍然可以确定所做的更改已同步到磁盘。 如果您需要更高的耐用性,当然您可以将写作关注点设置为{w:2}{w:"majority"}

优点

  1. 对于这种关系最常见的用例(显示给伪造一把剑的用户的链接),剑的文档中包含了所有需要这样做的信息,以防止可能的不必要的查询。
  2. 不过,如果用户点击所述链接,则可以有效地查询给定的剑的史密斯。
  3. 更改用户名是可能的,并且可以非常有效地和持久地实现

缺点

这里的主要缺点是,当用户改变用户名时,你实际上必须修改所有受影响的剑,而使用Mongoose引用是不必要的。 然而,由于这是一个罕见的用例,使用populate将导致整个用户文档被加载到只需要用户名的地方,我认为这个缺点是微不足道的。 基本上,您正在交易将常见用例所需的查询减less一半,而不需要手动更新,而这种更新很less发生。

我没有看到其他的缺点。

如果您使用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

编辑:请注意,我build议只保留在用户模型中的用户名称,只是引用它。