MongoDB/Mongoose 对日期字段的唯一约束

标签 mongodb mongoose mongodb-query

我已经在这样的架构上声明了一个唯一索引:

var stateChangeEventSchema = mongoose.Schema({
  client_timestamp: { type: Date, required: true, unique: true },
  state: { type: String, required: true }
})

并且能够插入具有相同时间戳的文档。我希望违反约束。我认为这可能是因为它在嵌入式文档上,但我在常规文档上尝试过,它仍然允许。我错过了什么?

编辑:我发现了问题。我未能创建另一个索引,无论出于何种原因阻止创建任何其他索引。

我通过使用找到了这个:

StateChange.on('index', function (err) {
  if (err) console.error(err);
})

网络:错误:'名称为:_id_的索引已存在,但选项不同'

发生这种情况是因为我有以下行:_id: { type: String, unique: true, 'default': shortId.generate }(为清楚起见在原始代码中进行了编辑 - 没有不认为它会影响任何东西)。

删除该行允许创建 client_timestamp 索引。

最佳答案

看起来您在进行此更改之前已经有重复的值。

这是一个测试用例。在部署索引之前,在您的集合中有两个这样的文档:

{ "timestamp" : ISODate("2014-06-02T04:09:22.683Z") }
{ "timestamp" : ISODate("2014-06-02T04:09:22.683Z") }

然后是基本列表:

    var mongoose = require('mongoose'),
        Schema = mongoose.Schema;

    mongoose.connect('mongodb://localhost/test');

    var stateChange = mongoose.Schema({
      timestamp: { type: Date, required: true, unique: true }
    });

    var Change = mongoose.model( 'Change', stateChange );

    var date = new Date();

    var change = new Change({
      timestamp: date
    });

    change.save(function(err,change) {

      if ( err )
        throw err;

      console.log( change );

      var new_change = new Change({
        timestamp: date
      });

      new_change.save(function(err,change) {

        if ( err )
          throw err;

        console.log( change );

      });

    });

您会看到两个文档都已添加。但这里的问题是索引没有部署,因为这导致了你没有看到的错误。您可以在 shell 中检查它。

db.changes.getIndicies()

这将显示您的唯一索引未创建:

[
    {
            "v" : 1,
            "key" : {
                    "_id" : 1
            },
            "name" : "_id_",
            "ns" : "test.changes"
    }
]

如果您重新开始并且只有一份来自原始文件的文件

{ "timestamp" : ISODate("2014-06-02T04:09:22.683Z") }

然后上面的代码示例创建索引并在第二个插入中产生错误:

{ __v: 0,
  timestamp: Mon Jun 02 2014 14:29:44 GMT+1000 (EST),
  _id: 538bfdb8961376867ae42e61 }

/xxxxx/node_modules/mongoose/lib/utils.js:413
    throw err;
          ^
MongoError: insertDocument :: caused by :: 11000 E11000 duplicate key error index: test.changes.$timestamp_1  dup key: { : new Date(1401683384647) }

这次正确创建的索引:

[
    {
            "v" : 1,
            "key" : {
                    "_id" : 1
            },
            "name" : "_id_",
            "ns" : "test.changes"
    },
    {
            "v" : 1,
            "unique" : true,
            "key" : {
                    "timestamp" : 1
            },
            "name" : "timestamp_1",
            "ns" : "test.changes",
            "background" : true,
            "safe" : null
    }
]

您将需要检查您的数据以删除现有的重复项或只接受使用 dropDups自动为您删除它们的选项。

另请参阅文档教程:Create A Unique Index

关于MongoDB/Mongoose 对日期字段的唯一约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23987130/

相关文章:

node.js - Mongoose 更新相互关系

node.js - 如何在 MongoDB 中正确执行批量更新插入/更新

javascript - 如何使用 MongoDB 和 Jade (Express.js) 通过 _id 删除文档?

mongodb - 如何在 mongodb 上配置 storage.smallFiles

node.js - 同时利用 GraphQL 和 Mongoose

javascript - 如果更新时属性的值为 null,则不应将该属性添加到记录中

javascript - 在 meteor 中使用mongo聚合来总计解锁/锁定集合

MongoDB 查询包含多个字段最常见值的计数

javascript - Mongoose findByIdAndUpdate 方法来切换和更新数据库中的 bool 值

node.js - 从 MongoDB 2.6 迁移到 3.2。我们可以跳过3.0获取数据吗?