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

Posted

技术标签:

【中文标题】在使用 Mongoose 创建对象之前检查唯一字段【英文标题】:Check for unique fields before creating object using Mongoose 【发布时间】:2018-04-13 02:24:38 【问题描述】:

我正在构建一个 GraphQL 服务器,我需要在将数据提交到数据库(MongoDB 和 Mongoose)之前进行某种验证。

其中一项检查与唯一字段相关。因此,一个模型可能有一个或多个唯一字段,我需要能够在保存到数据库之前对其进行检查。

所以,我已经构建了一些辅助函数来完成它,代码如下:

帮助代码:

import mongoose from "mongoose";

const isFieldUnique = (modelName, fieldName, fieldValue) => 

    let model = mongoose.model(modelName);
    let query = ;
    query[fieldName] = fieldValue;
    return model.findOne(query).exec();
;

const executeUniquePromises = (uniques, modelName, data) => 

    let promises = [];
    uniques.map(name => 

        let value = data[name];
        if (!value)
            throw new Error("Cannot test uniqueness for a null field.");

        promises.push(
            isFieldUnique(modelName, name, value)
            .then(value => 
                if (value) 
                    let error = name + ' is not unique';
                    console.log(error);
                    return error;
                

                console.log(name + ' is unique');
                return null;
            )
            .catch(error => 
                throw new Error(error);
            )
        )
    );

    return Promise.all(promises);
;

export const checkUniqueness = (uniques, modelName, data) => 

    return new Promise((resolve, reject) => 

        executeUniquePromises(uniques, modelName, data).then(result => 

            let errors = [];

            // Check for errors
            result.map((error) =>  
                if (error)
                    errors.push(error);
            );

            if (errors.length > 0)
                return reject(errors);
            else
                resolve();
        );
    );

Mongoose 静态创建函数:

import * as helper from './helper';

schema.statics.create = function (data) 

    let uniques = ['name', 'email'];
    helper.checkUniqueness(uniques,'Company', data)
    .then(result => 
            let user = new this(data);
            return company.save();
    )
    .catch(error => 
            throw new Error(error);
    );

GraphQL 代码:

const createUser = 
    type: UserType,
    description: "Create a user",
    args: 
        data: 
            name: "user",
            type: new GraphQLNonNull(UserInputType)
        
    ,
    resolve(root, args) 
        return UserModel.create(args.data);
    
;

帮助程序代码看起来很混乱,我没有将我的 Promise 与其他 Promise 一起使用是正确的做法。

请记住,我可能需要检查几个字段的唯一性,这就是我创建 promise 数组的原因。

一个问题是,当我在没有唯一匹配项的地方插入数据时,我的 GraphQL 服务器没有返回。

我想找到一种更好的方法,并找出为什么我没有取回保存的对象。

【问题讨论】:

【参考方案1】:

MongoDB 已经开箱即用地处理unique。在 Mongoose 模式中将该字段设置为 unique: true。您可以使用mongoose-beautiful-unique 使错误消息类似于验证错误消息。最后,当您无法让unique: true 工作时,请阅读this。

【讨论】:

我知道,但这对我的 GraphQL 服务器没有用,因为错误消息不是应用程序标准。 您只需几行就可以得到与普通验证错误完全一样的消息。唯一的缺点是在发送到数据库之前运行普通验证​​,而唯一约束由数据库本身检查。因此,普通验证消息永远不会与唯一验证消息同时显示。

以上是关于在使用 Mongoose 创建对象之前检查唯一字段的主要内容,如果未能解决你的问题,请参考以下文章

创建新模式对象后,Mongoose 引用的字段丢失

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

mongoDb/Mongoose:使 emailId 唯一字段[重复]

猫鼬中的唯一如果不是空检查

无法使用位置字段创建 Mongoose 对象

无法使用位置字段创建 Mongoose 对象