Mongoose 中的自增字段

Posted

技术标签:

【中文标题】Mongoose 中的自增字段【英文标题】:Auto-increment field in Mongoose 【发布时间】:2020-04-18 08:06:57 【问题描述】:

我正在尝试使用 Mongoose 创建一个 API,并且我有一个模型,我想在其中自动增加 postID 的值。 我有帖子架构

const PostSchema = new Schema(
    title: 
        type: String,
        required: true
    ,
    postID: 
        type: Number,
        unique: true,
        required: true
    ,
    body: 
        type: String,
        required: true
    ,
    author: 
        type: Schema.Types.ObjectId,
        ref: 'Author',
        required: true
    ,
    dateCreated: 
      type: Date,
      required: true
    ,
    lastModified: 
        type: Date,
        required: false
    ,
    modifiedBy: 
        type: Schema.Types.ObjectId,
        ref: 'Author',
        required: false
    ,
    picture: 
        type: mongoose.SchemaTypes.Url,
        required: false
    
, collection: 'Post');

我已经创建了一个预保存钩子

export const PostModel =  mongoose.model('Post', PostSchema);

PostSchema.pre('save', true, async function (next) 
    const post = this;
    post._id = new ObjectID();
    post.dateCreated = new Date();
    try 
        const lastPost = await PostModel.find(postID: $exists: true).sort(id: -1).limit(1);
        post.postID = lastPost.postID + 1;
     catch (e)
        console.log('could not take the last post')
    
    if(post && post.hasOwnProperty('body') && !post.body.isModified)
        return next();
    
    if(post && post.hasOwnProperty('body') && post.body.isModified)
        post.lastModified = new Date();
        return next();
    
);

处理添加创建日期和自动递增 postID。但是,每当我向 API 发送突变以创建新帖子时,我都会收到一个错误消息 Post validation failed: dateCreated: Path dateCreated is required., id: Path id is required. 这意味着 pre-save 钩子中处理的任何工作都没有完成。每当我向解析器添加一些随机值时,突变都会成功完成。知道为什么预保存不起作用吗?

这是我的解析器

module.exports.addPost = async(_,args, req) => 
    const post = new PostModel(
        title: args.post.title,
        body: args.post.body,
        author: new ObjectID(args.post.author),
        picture: args.post.picture
    );
    try 
        return await post.save();
     catch (e) 
        console.log('Could not save the post');
        console.log(e);
    
;

这里是突变

curl 'http://localhost:3001/graphql' -H 'Accept-Encoding: gzip, deflate, br' -H 'Content-Type: application/json' -H 'Accept: application/json' -H 'Connection: keep-alive' -H 'DNT: 1' -H 'Origin: http://localhost:3001' --data-binary '"query":"mutation($post: PostInput)\n  addPost(post: $post)\n    title\n    body\n    author\n  \n","variables":"post":"title":"newTitle","body":"Lorem ipsum","author":"5e07e6c07156cb000092ab45","picture":"http://www.example.com"' --compressed

【问题讨论】:

可能与您的问题无关,但如果您已经在使用 async/await 或从钩子返回 Promise,则无需调用 next() 查看docs 中的示例,看起来true 不是有效参数。试试:PostSchema.pre('save', async function (next) 【参考方案1】:

上面的 sn-p 不起作用。根据 Mongoose 的文档,编译模型后调用 pre 或 post 钩子不起作用。所以你应该搬家

export const PostModel =  mongoose.model('Post', PostSchema);

在预挂钩下方。此外,由于尚未定义 PostModel 并且您想要获取插入数据库的对象的最后一个 id,您可以将此检查移至解析器。

   let lastPost = await PostModel.find(id: $exists: true).sort(id: -1).limit(1); 
    // This always returns an array, either empty or with data
    if(Array.isArray(lastPost) && lastPost.length > 0)
        lastPost = lastPost[0]
    
    const post = new PostModel(
        ...
        id: lastPost['id'] + 1
        ...
    );
    if(Array.isArray(lastPost) && lastPost.length === 0) 
        post.id = 0;
    // If this lastPost is an empty array and you try to access the id property
    // you will get an error that NaN to Int conversion failed
    

希望对你有帮助

【讨论】:

以上是关于Mongoose 中的自增字段的主要内容,如果未能解决你的问题,请参考以下文章

mongoose更新文档的时候让某个字段自增

关于 mysql 事务中的自增 id 的疑问

mysql 中删除主键字段的自增属性和约束属性

SQL server中设置自增字段

Oracle 怎样查询所有自增的序列名

如何得到SqlServer的自增ID