Mongoose:如何将字段组合定义为唯一?

Posted

技术标签:

【中文标题】Mongoose:如何将字段组合定义为唯一?【英文标题】:Mongoose: how to define a combination of fields to be unique? 【发布时间】:2013-04-10 07:35:02 【问题描述】:

如果我有这样的架构:

var person = new Schema(
  firstName:  String,
  lastName: String,
);

我想确保只有一个文件具有相同的名字和姓氏。

我怎样才能做到这一点?

【问题讨论】:

【参考方案1】:

您可以在架构上使用 index 调用来定义唯一的复合索引:

person.index( firstName: 1, lastName: 1,  unique: true );

【讨论】:

@chovy 您不需要删除集合,但您需要删除字段上的任何现有复合索引。 我没有现有的复合索引。但是即使在重新启动我的应用程序服务器之后,我也能够很好地(重复地)添加重复项。直到我放弃了收藏。 这在第一次尝试时对我有用,无需以任何其他方式删除或修改集合 只有满足独特要求时才会创建索引。这解释了为什么@chovy 不得不放弃他的收藏(可能只是删除重复项) 要确定哪些重复项会阻止索引粘连,您可以这样做:Model.on('index', function(err) console.log(err) );【参考方案2】:

我最近才通过 Mongoose 的实验发现了一个有趣的小东西。例如,我有以下架构:

const ShapesSchema = new mongoose.Schema(
  name:  type: String, required: true ,
  user:  type: mongoose.Schema.Types.ObjectId, ref: 'User' 
)

ShapesSchema.index( name: 1, user: 1 ,  unique: true )

mongoose.model('Shapes', ShapesSchema)

这个想法是创建一个在 nameuser 上唯一的复合索引。这样,只要每个形状都有一个不同的名称,用户就可以根据需要创建任意数量的形状。反过来也应该是正确的——形状可以有相同的名称,只要它们有不同的用户。对我来说不是这样。

我注意到除了_id 上的索引之外,还创建了其他三个索引条目。 nameusername_user 各有一个,都设置为唯一。我对架构进行了修改,并将unique: false 包含到我用于复合索引的每个字段中,突然间一切都按预期工作了。我最终得到的是:

const ShapesSchema = new mongoose.Schema(
  name:  type: String, required: true, unique: false ,
  user:  type: mongoose.Schema.Types.ObjectId, ref: 'User', unique: false 
)

ShapesSchema.index( name: 1, user: 1 ,  unique: true )

mongoose.model('Shapes', ShapesSchema)

查看作为结果创建的索引,我仍然看到三个索引 - nameusername_user。但不同之处在于,前两个不是唯一的,而最后一个是化合物。现在,我的每个用户使用多个不同形状的用例,或者具有不同用户的同名形状就像一个冠军。

【讨论】:

这对我帮助很大。我还需要在此处根据文档添加mongoose.connect(uri, useCreateIndex: true );:mongoosejs.com/docs/guide.html#indexes【参考方案3】:

像这样定义你的架构


var person = new Schema(
firstName:  String,
lastName: String,
index: true,
unique: true, 

);


person.index( firstName: 1, lastName: 1,  unique: true );

【讨论】:

【参考方案4】:
const personSchema = new Schema( firstName:  String, lastName: String );
const person = mongoose.model('recipients', personSchema);
person.createIndexes();

您可能需要删除集合中的所有重复项,或者以更快更简单的方式进行:

编辑您的代码,删除集合,然后重新启动 Mongo。

【讨论】:

【参考方案5】:

我还没有尝试过,但是使用唯一索引应该可以解决问题。

db.person.ensureIndex(  "firstname": 1, "lastname": 1 ,  unique: true  )

【讨论】:

这在猫鼬中没有实现 对我来说猫鼬没有调用 ensureIndex 所以这对我有用,谢谢【参考方案6】:

您可以像这样定义您的架构。

const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const bcrypt = require("bcryptjs");

    const userSchema = new Schema(
      firstName: 
        trim: true,
        type: String,
        required: [true, "firstName is required!"],
        validate(value) 
          if (value.length < 2) 
            throw new Error("firstName is invalid!");
          
        
      ,
      lastName: 
        trim: true,
        type: String,
        required: [true, "lastName is required!"],
        validate(value) 
          if (value.length < 2) 
            throw new Error("lastName is invalid!");
          
        
      ,
      username: 
        unique: [true, "Username already available"],
        type: String,
        required: [true, "Username is required"],
        validate(value) 
          if (value.length < 10) 
            throw new Error("Username is invalid!");
          
        
      ,
      mobile: 
        unique: [true, "Mobile Number alraedy available"],
        type: String,
        required: [true, "Mobile Number is required"],
        validate(value) 
          if (value.length !== 10) 
            throw new Error("Mobile Number is invalid!");
          
        
      ,
      password: 
        type: String,
        required: [true, "Password is required"],
        validate(value) 
          if (value.length < 8) 
            throw new Error("Password is invalid!");
          
        
      ,
      gender: 
        type: String
      ,
      dob: 
        type: Date,
        default: Date.now()
      ,
      address: 
        street: 
          type: String
        ,
        city: 
          trim: true,
          type: String
        ,
        pin: 
          trim: true,
          type: Number,
          validate(value) 
            if (!(value >= 100000 && value <= 999999)) 
              throw new Error("Pin is invalid!");
            
          
        
      
      date:  type: Date, default: Date.now 
    );

【讨论】:

这对firstName, lastName 的独特之处究竟是什么?

以上是关于Mongoose:如何将字段组合定义为唯一?的主要内容,如果未能解决你的问题,请参考以下文章

在 Node.js Mongoose 中,我想更新每个字段……我该怎么做?

从 Mongoose 获取模式中设置为唯一的字段

如何将自定义 ObjectId 添加到解析服务器对象?

MongoDB/Mongoose - 仅当某个字段是唯一的时才将对象添加到对象数组中

在使用 Mongoose 创建对象之前检查唯一字段

在 Mongoose Schema 中使用多个值的唯一文档