Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mongodb Mongoose模式:使数组中的对象具有文档的唯一字段_Mongodb_Express_Mongoose_Mongodb Query_Mongoose Schema - Fatal编程技术网

Mongodb Mongoose模式:使数组中的对象具有文档的唯一字段

Mongodb Mongoose模式:使数组中的对象具有文档的唯一字段,mongodb,express,mongoose,mongodb-query,mongoose-schema,Mongodb,Express,Mongoose,Mongodb Query,Mongoose Schema,我不是在尝试创建一个唯一的数组元素,而是要确保如果我有一个对的数组(它们是对象),那么所有对都有不同的值 以下是我的模式的定义: const redirectSchema = new mongoose.Schema({ username: { type: String, required: true, }, name: { type: String, required: true, uniqu

我不是在尝试创建一个唯一的数组元素,而是要确保如果我有一个
对的数组(它们是对象),那么所有
都有不同的值

以下是我的模式的定义:

const redirectSchema = new mongoose.Schema({
    username: {
        type: String,
        required: true,
    },
    name: {
        type: String,
        required: true,
        unique: true
    },
    default_link: {
        type: String,
        required: true,
    },
    pairs: [
        {
            code: { // I want this field specifically to be unique within the document only
                type: String,
                required: true
            },
            site: {
                type: String,
                required: true
            }

        }
    ],
    date: {
        type: Date,
        required: true,
        default: Date.now
    }
})
例如,像这样插入一对
就可以了

{
    code: "US",
    site: "google.com"
}
但是,在本文档中插入另一个具有相同
代码的
,无论是
站点
,都是不合适的

{
    code: "US", // Should not work, since the code "US" already exists within the array of pairs
    site: "amazon.com"
}
我正在尝试使用
Redirect.findOne()
Redirect.updateOne()
执行此操作,但我收到了编译器错误,或者只有在存在重复项后才会执行检查

这是我到目前为止的路线(允许重复
code
s):


我的代码中的问题在于,我使用了
forEach
查找来遍历文档数组中的
对对象。

由于我在我的
POST
路径中使用了
async
函数,因此我进行了一些搜索,发现
forEach
函数在
async
函数中不能很好地发挥作用。

这是我的密码

  • 获取文档并检查
    数组

  • 如果
    pairs
    包含具有请求代码的对象,则返回错误消息

  • 如果不是,则将
    对象添加到文档中

  • //将对添加到给定重定向
    router.post('/:name/insert_pair',verifyToken,异步(请求,响应)=>{
    const token=request.header(“身份验证令牌”)
    const usernameFromToken=jwt.decode(token).username
    const{code,site}=request.body
    //请记住:您只能编辑自己的内容
    试一试{
    //将对象作为纯JSON获取,并检查它是否包含代码
    const check=wait Redirect.findOne(
    {
    用户名:usernameFromToken,
    名称:request.params.name
    }
    ).lean()
    //解决方案:不要在异步中使用FOREACH!
    for(设i=0;i{
    //如果(pair.code==代码){
    //返回response.status(400.json)({
    //消息:`${request.params.name}已包含${code}的条目`
    //         })
    //     }
    // })
    //编辑
    等待重定向。findOneAndUpdate(
    {
    用户名:usernameFromToken,
    名称:request.params.name
    },
    {
    $push:{
    成对:{code,site}
    }
    }
    )
    //让它显示在屏幕上
    const display=await Redirect.findOne(
    {
    用户名:usernameFromToken,
    名称:request.params.name
    })
    json(显示)
    }捕获(错误){
    response.status(400.json)(错误)
    }
    })
    
    // Add pair to given redirect
    router.post('/:name/insert_pair', verifyToken, async (request, response) => {
        const token = request.header("auth-token")
        const usernameFromToken = jwt.decode(token).username
    
        const { code, site } = request.body
    
        // Remember: you may edit only your own content
        try {
            const edited = await Redirect.findOneAndUpdate(
                {
                    username: usernameFromToken,
                    name: request.params.name
                },
                {
                    $push: {
                        pairs: { code, site }
                    }
                }
            )
    
            const specific = await Redirect.findOne(
                {
                    username: usernameFromToken,
                    name: request.params.name
                })
    
            response.send(specific)
        } catch (error) {
            response.status(400).json(error)
        }
    
    // Add pair to given redirect
    router.post('/:name/insert_pair', verifyToken, async (request, response) => {
        const token = request.header("auth-token")
        const usernameFromToken = jwt.decode(token).username
    
        const { code, site } = request.body
    
        // Remember: you may edit only your own content
        try {
            // Get the object as plain JSON and check if it contains the code
            const check = await Redirect.findOne(
                {
                    username: usernameFromToken,
                    name: request.params.name
                }
            ).lean()
    
            // SOLUTION: DON'T USE FOREACH WITHIN ASYNC!
            for (let i = 0; i < check.pairs.length; i++) {
                if (check.pairs[i].code === code) {
                    return response.status(400).json({
                        message: `${request.params.name} already contains an entry for ${code}`
                    })
                }
            }
    
            // TODO BUG: ONLY WORKS AFTER 1 DUPLICATE HAS ALREADY BEEN MADE.
            // await check.pairs.forEach((pair) => {
            //     if (pair.code === code) {
            //         return response.status(400).json({
            //             message: `${request.params.name} already contains an entry for ${code}`
            //         })
            //     }
            // })
    
            // Make the edit
            await Redirect.findOneAndUpdate(
                {
                    username: usernameFromToken,
                    name: request.params.name
                },
                {
                    $push: {
                        pairs: { code, site }
                    }
                }
            )
    
            // Get it to display it on screen
            const display = await Redirect.findOne(
                {
                    username: usernameFromToken,
                    name: request.params.name
                })
    
            response.json(display)
        } catch (error) {
            response.status(400).json(error)
        }
    })