独特和稀疏的模式级索引MongoDB和Mongoose

时间:2014-11-11 23:11:55

标签: node.js mongodb mongoose unique-index mongodb-indexes

我正在尝试使用Mongoose在MongoDB中的两个模式字段中创建一个唯一且稀疏的索引,如下所示:

var ArraySchema = new Schema ({
    user_id: {type: mongoose.Schema.Types.ObjectId, ref:'User'},
    event_id: {type: mongoose.Schema.Types.ObjectId, ref:'Event'}
}, {_id:false});

ListSchema.index({user_id:1, event_id:1}, {sparse:true, unique:true});

然后在User模式中的数组中使用它:

var User = new Schema({
    arrayType1 : {
        type: [ArraySchema]
    },
    arrayType2 : {
        type: [ArraySchema]
    },
    arrayType3 : {
        type: [ArraySchema]
    }
    //More specifications for user schema...
});

但是,在尝试保存没有array字段的多个用户时,会抛出重复字段的错误。 Mocha中的错误类似于:array.event_id_1 dup key {null, null}。抛出此错误的代码段示例如下:

var user1, user2;

user1 = new User({
    username : 'username1',
    password : 'password'
});

user2 = new User({
    username : 'username2',
    password : 'password'
});

user1.save(function() {
    user2.save();
});

我的理由是使ArraySchema的字段唯一且稀疏:如果指定了array字段,我不希望该数组包含重复的对象;但是,array字段不是必需的,因此会有许多用户对此字段null。显然我不能使用字段级索引,因为有多个字段需要索引(arrayType1arrayType2arrayType3)。

1 个答案:

答案 0 :(得分:1)

似乎不支持这样做,至少在这个时候。另一种方法是在这些字段上创建复合索引,然后每当向字段添加新元素时使用user.arrayType1.addToSet()。以下是一个如何工作的示例:

<强> ArraySchema:

var ArraySchema = new Schema ({
     user_id: {type: mongoose.Schema.Types.ObjectId, ref:'User'},
     event_id: {type: mongoose.Schema.Types.ObjectId, ref:'Event'}
}, {_id:false});

ListSchema.index({user_id:1, event_id:1});

用户架构:

var User = new Schema({
    arrayType1 : {
        type: [ArraySchema]
    },
     arrayType2 : {
         type: [ArraySchema]
    },
    arrayType3 : {
        type: [ArraySchema]
    }
    //More specifications for user schema...
});

然后我可以照常宣布新用户(正如我在问题中所做的那样);但是,当我想向arrayType1添加新元素时,我会使用以下代码行添加到新元素(如果它还没有):

user.arrayType1.addToSet({user_id : user2._id, event_id : event._id});
user.save(function(err, result) {
    //Callback logic.
};

其中user2event在代码中先前定义并保存到数据库中。或者,我可以使用Mongoose的更新功能:

User.update({_id : user._id}, {
        $addToSet : {
            arrayType1 : {
                user_id : user2._id,
                event_id : event._id
            }
        }
    }, function(err) {
        //Callback logic.
    }
);