【问题标题】:how to insert autoincrement number with my mongoose collection如何在我的 mongoose 集合中插入自动增量编号
【发布时间】:2020-09-30 21:19:34
【问题描述】:

我是猫鼬的新手,我有一个像这样的猫鼬模式:

var user = mongoose.Schema({
    userID: {
        type: String,
        required:true
    },
    seq: {
        type: Number,
        default: 0
    },
    firstname: {
        type: String
    },
    lastname: {
        type: String
    },
    dob: {
        type: String
    },
    email: {
        type: String,
        required: true
    },
    username: {
        type: String,
        required: true
    },
    displayname: {
        type: String
    },
    password: {
        type: String,
        required: true
    },
    mobile: {
        type: String
    },
    profilePic: {
        type: String
    },
    city: {
        type: String
    },
    gender: {
        type: String
    },
    profileType: {
        type: String,
        required: true
    },
    profileId: {
        type: String
    },
    isActive: {
        type: Number
    },
    ageVerified: {
        type: String
    },
    ipAddress: {
        type: String
    },
    key: {
        type: String
    },
    osType: {
        type: String
    },
    osVersion: {
        type: String
    },
    deviceName: {
        type: String
    },
    joinedDate: {
        type: String
    },
    connectedAccounts: [{
        profileType: {
            type: String
        },
        profileId: {
            type: String
        },
        email: {
            type: String
        }
    }]
}, {collection: 'user'});

请注意,用户 ID 是一个自动递增的数字字段,用于插入值 am 使用 mongoose 查询,例如:

new user(contents).save(function (err,doc){};

'contents' 是一个对象,其中包含除 userID 之外的所有字段的数据,这里我的问题是如何在插入其他字段的记录时插入 userID(自动增量编号)的值?我参考这个link来设置自动增量值......但我不知道如何在猫鼬中使用它?

【问题讨论】:

  • 或者我们是否可以在添加新记录时将自动增量数字添加到 mongodb 中?有可能吗?
  • 您的用户 ID 不是数字而是字符串。你有整篇文章在这里:docs.mongodb.org/manual/tutorial/…
  • 为什么您需要这个自动递增字段? Mongo 在_id 字段中为您提供了一个唯一标识符。这还不够吗?

标签: node.js mongodb mongoose


【解决方案1】:

按照 MongoDB 教程 Create an Auto-Incrementing Sequence Field,您需要先创建一个单独的 counters 集合来跟踪使用的最后一个数字序列。 _id 字段包含序列名称,即用户集合中的userID 字段,seq 字段包含序列的最后一个值。

首先,将userID 的初始值插入到计数器集合中:

db.counter.insert(
   {
      "_id": "userID",
      "seq": 0
   }
)

填充计数器集合后,在 Mongoose 中生成其架构:

var counterSchema = mongoose.Schema({
    "_id": { "type": String, "required": true },
    "seq": { "type": Number, "default": 0 }
});

var counter = mongoose.model('counter', counterSchema);

然后重新定义您的用户模式,以便在您保存用户模型时,它首先调用计数器模型的 findByIdAndUpdate() 方法来原子地递增 seq 值并返回这个新值,然后可以将其用作下一个 userID 值:

var userSchema = mongoose.Schema({
    "userID": { "type": String, "required": true },
    "firstname": { "type": String },
    "lastname": { "type": String },
    // other properties ...
    }, { "collection": "user" }
);

userSchema.pre("save", function (next) {
    var doc = this;
    counter.findByIdAndUpdate(
        { "_id": "userID" }, 
        { "$inc": { "seq": 1 } }
    , function(error, counter)   {
        if(error) return next(error);
        doc.userID = counter.seq.toString();
        next();
    });
});

【讨论】:

  • 感谢您的帖子..!在执行时,它会在“doc.userID = counter.seq.toString();”处引发类似“TypeError: Cannot read property 'seq' of null”的错误。
  • @Karthik 在尝试保存user 模型之前,您是否首先将userID 的初始值插入到counters 集合中?
  • 你有没有提到,我必须在 mongodb 的“计数器”集合中插入一行
  • @Karthik 你必须先创建集合,我什至在我的回答中明确提到过 首先,将 userID 的初始值插入到 counters 集合中:
  • 我创建了一个计数器集合,其初始值类似于 {"_id":"500",seq:0}。仍然在“doc.userID = counter.seq.toString();”处抛出相同的错误“TypeError: Cannot read property 'seq' of null”
【解决方案2】:

如果你想要一个基于集合长度的自动增量道具,你可以这样做:

UserSchema.pre("save", function (next) {
  if (this.isNew) {
    this.constructor.find({}).then((users) => {
      this.autoIncrementProp = users.length + 1;
      next();
    });
  }
});

isNew 是保留的 Schema 名称(布尔标志,指定文档是否是新的。

【讨论】:

    【解决方案3】:

    考虑到schema.findByIdAndUpdate 的逻辑是“返回当前值然后递增”,您还可以使用@chridam 的解决方案,并进行以下编辑:

    var counter = mongoose.model('counter', counterSchema);
    
    
    userSchema.pre("save", function (next) {
      var doc = this;
      counter.findByIdAndUpdate(
          { "_id": "userID" }, 
          { "$inc": { "seq": 1 } }
      , function(error, c /*counter*/)   {
          if(error)
            return next(error);
          else if(!c) {
            c = new counter({ _id: "userID" }, { $inc: { seq: 1 } };
            c.save(function() {
              doc.userID = (c.seq - 1) + '';
              next();
            });
          } else {
            doc.userID = counter.seq.toString();
            next();
          }
      });
    });
    

    请注意,此解决方案使您的代码从头开始运行,而不会强制您初始化数据库。

    诀窍在于循环的第一轮。 counter 未定义,因此您需要对其进行初始化,但如果您将其初始化为 0,则接下来勾选代码尝试再次分配 userID=0

    这是因为一方面存在schema.findByIdAndUpdate 的逻辑,它首先读取值然后递增它,另一方面您需要一个逻辑来先分配值。

    您可以通过使算法跳过第一步并如上所述设置变量值来加入这两个逻辑。

    注意:counterSchema 与 chridam 的相同:

    counterSchema = mongoose.Schema({
      "_id": { "type": String, "required": true },
      "seq": { "type": Number, "default": 0 }
    });
    

    【讨论】:

    • 那很好,我一直在寻找这样的东西,但我在想如果要删除用户怎么办,userId 是否会重新调整以仍然遵循它的正常编号顺序。例如,如果我们有 123,而 2 被删除,那么 3 会变成 2。
    • 不幸的是,计数器不能填补空白。如果您描述的此类行为频繁发生,则系统往往会出现多个漏洞。
    猜你喜欢
    • 2020-11-09
    • 2013-01-05
    • 1970-01-01
    • 1970-01-01
    • 2012-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多