如何在MongoDB中创建持久唯一索引

问题描述:

声明:我使用猫鼬的时间少于48小时。如何在MongoDB中创建持久唯一索引

我有一个模型,看起来像这样:

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

//Schema definition 
var CategorySchema = new Schema({ 
    name: String, 
    url: { type: [String], index: true }, 
    extra: Array, 
    frequency: Number, 
    last_processed: Date 
}); 

// Model definition 
var Category = mongoose.model('categories', CategorySchema); 

当我的应用程序启动,它有一个方法来自动更新集合,使用结构类似于以下(js文件一个js文件,该文件是不我的控制之下):

var categories = { 
    retailer: 'ret1', 
    name: 'c1', 
    url: 'url1', 
    extra: ['tag1'], 
    frequency: 2, 
    last_processed: '' 
}, { 
    retailer: 'ret2', 
    name: 'c2', 
    url: 'url2', 
    extra: ['tag2'], 
    frequency: 2, 
    last_processed: '' 
}, 
    ........ 
]; 

module.exports = categories; 

我创建使用循环记录:

var Category = mongoose.model('categories'); 
for (var j = 0; j < categories.length; j++) { 
    new Category(categories[j]).save(); 
} 

我的问题是这样的:

当我启动我的应用程序在第一时间,db.categories.count()= 308(因为它应该是)。如果我关闭应用程序并重新启动,count()= 616,所以它复制记录。我认为使用索引可以避免这种行为,但显然不是。关于索引的文档并不清楚,来自RDB背景。我在调试中看到索引已创建:Mongoose: categories.ensureIndex({ url: 1 }) { safe: undefined, background: true }

如何在我的集合上创建持久性唯一索引,以便我从不重复?在这个简单的启动例程之后,我会不断地写在这张表上,每次写入后我是否必须重新创建一个索引?更多的研究后

更新:

我在308周的网址我写不重复,我从一个空数据库启动。

您可以定义唯一索引:

var CategorySchema = new Schema({ 
    name: String, 
    url: { 
     type: String, 
     index: { 
      unique: true 
     } 
    }, 
    extra: Array, 
    frequency: Number, 
    last_processed: Date 
}); 

然后,给你一个回调添加到save()

for (var j = 0; j < categories.length; j++) { 
    new Category(categories[j]).save(function(err, doc) { 
     console.error(err); 
    }); 
} 

您将看到以下印刷

{ [MongoError: insertDocument :: caused by :: 11000 E11000 duplicate key error index: test.categories.$url_1 dup key: { : "url2" }] 
    name: 'MongoError', 
    code: 11000, 
    err: 'insertDocument :: caused by :: 11000 E11000 duplicate key error index: test.categories.$url_1 dup key: { : "url2" }' } 

你可以使用findOneAndUpdate其中,给出选项upsert: true,woul d创建或更新对象。如果您不想更新,但只是跳过,因为使用save()的类别可能足够好。

for (var j = 0; j < categories.length; j++) { 
    Category.findOneAndUpdate(
     { url: categories[j].url }, 
     categories[j], 
     { upsert: true }, 
     function(err, doc) { 
      console.error(err); 
     } 
    ); 
} 
+0

是的,这是纠正索引中的错字(我相信是从文档copypasted)后工作。谢谢! – xShirase 2014-10-27 09:44:06