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

Posted

技术标签:

【中文标题】日期字段上的 MongoDB/Mongoose 唯一约束【英文标题】:MongoDB/Mongoose unique constraint on Date field 【发布时间】:2014-07-22 03:12:51 【问题描述】:

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

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

其中网:err: 'Index with name: _id_ already exists with different options'

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

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

【问题讨论】:

【参考方案1】:

在您进行此更改之前,您似乎已经有重复的值。

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

 "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

【讨论】:

嗯。我已删除我的数据库并再次尝试。索引未正确创建。 @DominicBou-Samra 你在这里做错了你没有解释的事情。如上所示的案例是从一个空白数据库生成的,并且可以在结果中重现。 啊,我找到了。编辑主帖 Hmmmmmm 这适用​​于非嵌入文档,但嵌入时仍然失败。 @DominicBou-Samra 我不知道你在问什么。您似乎在您发布的问题中未包含的详细信息中发现了问题。您现在是否在询问未包含在您发布的问题中的更多细节?

以上是关于日期字段上的 MongoDB/Mongoose 唯一约束的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB/Mongoose:在填充字段中排序

MongoDB/Mongoose:保存 > 将评论推送到数组中,在数组中你会看到评论 + 日期

mongoDb/Mongoose:使 emailId 唯一字段[重复]

如何使用 MongoDB/Mongoose 中的先前值更新字段 [重复]

使用嵌套字段在MongoDB / Mongoose中创建多对多关系?

根据另一个字段值 mongodb mongoose 从文档中排除字段