复合索引无效?

3

我正在尝试使用Mongoose创建复合索引:

var ProjectSchema = new mongoose.Schema({
    name: {type: String, required: true},
    user: {type: mongoose.Schema.ObjectId, ref: 'User', required: true}
});

ProjectSchema.index({user: 1, name: 1}, {unique: true});

然后我在 mongo 中删除了旧的数据库。

db.dropDatabase()

但我仍然可以使用相同的名称和用户ID插入多个文档。为什么?

它创建的索引在mongo中显示为:

> db.projects.getIndexes();
[
    {
        "v" : 1,
        "key" : {
            "_id" : 1
        },
        "ns" : "mydatabase.projects",
        "name" : "_id_"
    }
]
4个回答

2

这是纯粹的Mongo控制台功能,它可以工作。点击这里了解更多细节。这不在mongoose的API中描述。我认为它可能有效。

db.collection.ensureIndex( { a: 1 }, { unique: true, dropDups: true } )

谢谢。不知道为什么现在它可以工作了。 - akonsu
"dropDups: true" 的意思是它会删除所有重复的文档并使您的集合变得唯一。 - Hardik Barot
1
@Hardik,但这也无关紧要,因为在运行代码之前数据库被删除了。因此,在启动时不会有任何东西。我怀疑这是一个回调问题,因为从问题中可以看出索引从未被创建。 - Neil Lunn

2

实际上,您的索引似乎尚未创建。您只显示了默认的主键。您从.getIndexes()获得的输出应该更像:

> db.projects.getIndexes()
[
    {
            "v" : 1,
            "key" : {
                    "_id" : 1
            },
            "ns" : "project.projects",
            "name" : "_id_"
    },
    {
            "v" : 1,
            "key" : {
                    "user" : 1,
                    "name" : 1
            },
            "unique" : true,
            "ns" : "project.projects",
            "name" : "user_1_name_1",
            "background" : true,
            "safe" : null
    }
]

你的代码可能有问题,但这个对我有效:

var mongoose = require('mongoose');

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

var db = mongoose.connection;
var Schema = mongoose.Schema;

var UserSchema = new Schema({
  name: { type: String, required: true },
  info: String
});

var ProjectSchema = new Schema({
    name: { type: String, required: true},
    user: { type: Schema.ObjectId, ref: 'User', required: 'true'}
});

ProjectSchema.index({ user: 1, name: 1}, { unique: true });

var User = mongoose.model( "User", UserSchema );
var Project = mongoose.model( "Project", ProjectSchema );

var user = new User({ name: "me" });
user.save(function(){

  var project = new Project({ name: "Project1", user: user._id });
  project.save(function(err, project, numAffected){

    if (err) {            // Should be fine
      console.log(err);
    }

    console.log("First project created");

    User.findOne({}).exec(function(err, user) {

      console.log(user._id);

      var project = new Project({ name: "Project1", user: user._id });
      project.save(function(err, project, numAffected){

        if (err) {
          console.log(err); // Expect a problem here
        }

        console.log({ project: project, num: numAffected });

      });

    });

  });

});

1
OP...为什么这个答案被接受了?它似乎没有对你的代码进行任何更正。我和你遇到了同样的问题,但还是没有任何线索可以解决问题… - anthonygore

1
我曾经遇到同样的问题,这个Github问题解释了发生了什么。
首先,复合索引只有在调用ensureIndex()之后才会创建。对我来说,问题在于我使用了一个导入脚本来删除我的数据库并重新创建它。只有在服务器重新启动后才会调用ensureIndex(),因此复合索引在此之后没有重新创建。
对我来说,解决方案是不在我的导入脚本中删除数据库,而是遍历我的模型并删除所有文档。这样数据被销毁,但索引保留,因此复合索引将起作用。

只是为了准确起见,需要重新启动Mongoose服务器,而不仅仅是Mongo。 - ypicard

0

我刚遇到了这个问题,启动时未创建复合索引,我检查了Mongo日志,发现它正在开始构建索引,但没有创建任何内容,也没有错误等...

然后我尝试手动创建索引 - 在Mongo控制台中 - 这里出现了一个错误(在我的情况下是重复错误),所以我删除了重复项,然后成功创建了索引。我不知道为什么这个问题没有在我的Mongo日志中弹出。

Mongo v4


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接