【问题标题】:How to ensure uniqueness of certain fields when creating a new document in MongoDB?在 MongoDB 中创建新文档时如何确保某些字段的唯一性?
【发布时间】:2019-08-11 02:48:08
【问题描述】:

我想使用唯一的复合索引来强制文档中某些字段的唯一性。

使用mongoose时创建索引有两种方式:

  1. 通过重启 MongoDB
  2. 致电Model.ensureIndexes()

(1.) The mongoose documentation clearly states那个

当您的应用程序启动时,Mongoose 会自动 为架构中定义的每个索引调用 createIndex。
[...]
虽然很适合开发,但建议在生产中禁用此行为,因为创建索引会导致 significant performance impact

而且,每次将新文档添加到集合中时重新启动数据库似乎并不真正“高效”。


第二种创建索引的方法也是如此:

不建议您在生产环境中运行它。根据您的负载,索引创建可能会影响数据库性能。谨慎使用。
Source

将此问题扩展到特定示例:

对于每个文档,两个特定字段的组合应该是唯一的(例如“年份”和“课程”),因此我使用了唯一的复合索引。
保存新文档后,可能会有第二个具有相同值的请求会触发错误,因为它是重复的。
如果尚未创建索引,则无论如何都会保存该文档。 所以它是关于(正如标题试图强调的那样)确保唯一性。也许每次保存新文档时都使用索引并重建它们不是正确的方法;我对替代方案持开放态度。

那么我们应该如何确保唯一性呢?

【问题讨论】:

标签: node.js mongodb mongoose


【解决方案1】:

来自文档:https://mongoosejs.com/docs/faq.html

MongoDB 保留索引,因此如果您从新数据库开始或运行 db.dropDatabase(),则只需重建索引。

一旦创建索引,MongoDB 将保持它们是最新的。因此,当添加新文档时,我们不需要手动重建索引。

在启动时,我们可以等到新索引准备好:

Model.init().then(function() {
    // indexes are ready here
    Model.create([{ name: 'Val' }, { name: 'Val' }], function(err) {
    });
});

还要记住:

在生产环境中,您应该[使用 MongoDB shell 创建索引])(https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/) 而不是依靠 mongoose 为您完成。

【讨论】:

  • 那您对此有何解释? mongoosejs.com/docs/faq.html#unique-doesnt-work 当然,他们很坚持,但是However, if you wait for the index to build using the Model.on('index') event, attempts to save duplicates will correctly error. 他们需要时间来构建。如果在构建期间,有另一个具有相同值的保存请求怎么办?会有一个副本。我想防止这样的重复。
  • 在这个例子中,我们不等待建立索引,所以流程将是:1)我们有没有索引的新数据库 2)初始化 mongoose 并开始由 mongoDB 在后台建立索引 3)当索引还没有准备好时立即调用 create > 成功 4) 索引准备好了
  • 如何防止我在您的答案下方的第一条评论中提到的参考文章中提到的重复?
  • 另外,当您部署应用程序时,我们只讨论新索引,您不会经常添加索引。如果您想确保所有索引都存在 - 您必须等到所有模型都被初始化(Model.init() 在每个模型上解析),然后才能启动您的应用程序。但这是不寻常的策略......
  • ...或者,按照 mongoose 文档中的建议,您应该首先使用 MongoDB shell 构建索引,然后部署依赖于该索引的应用程序。在这种情况下,您可以确定一切都按预期进行。
猜你喜欢
  • 1970-01-01
  • 2014-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-22
  • 2016-06-29
  • 1970-01-01
相关资源
最近更新 更多