条件更新,取决于匹配的字段

时间:2016-05-26 09:54:30

标签: node.js mongodb mongodb-query

假设我有一系列文件,每个文件都在管理老师和学生之间的讨论:

{
    _id,
    teacherId,
    studentId,
    teacherLastMessage,
    studentLastMessage
}

我将通过3个参数获得查询:_iduserIdmessage
我正在寻找一种方法来更新teacherLastMessage字段或studentLastMessage字段,具体取决于用户所在的字段。

目前,我有这个:

return Promise.all([

    // if user is teacher, set teacherLastMessage
    db.collection('discussions').findOneAndUpdate({
        teacherId: userId,
        _id
    }, {
        $set: {
            teacherLastMessage: message
        }
    }, {
        returnOriginal: false
    }),

    // if user is student, set studentLastMessage
    db.collection('discussions').findOneAndUpdate({
        studentId: userId,
        _id
    }, {
        $set: {
            studentLastMessage: message
        }
    }, {
        returnOriginal: false
    })


]).then((results) => {
    results = results.filter((result) => result.value);

    if (!results.length) {
        throw new Error('No matching document');
    }

    return results[0].value;
});

有没有办法告诉mongo根据匹配的字段进行条件更新?像这样:

db.collection('discussions').findOneAndUpdate({
    $or: [{
        teacherId: userId
    }, {
        studentId: userId
    }],
    _id
}, {
    $set: {
    // if field matched was studentId, set studentLastMessage
    // if field matched was teacherId, set teacherLastMessage
    }
});

肯定有可能使用mongo 3.2吗?

2 个答案:

答案 0 :(得分:1)

您想要的是需要引用$set内的其他字段。目前这是不可能的。请参阅this ticket作为示例。

首先,您当前使用两个更新查询的方法对我来说很合适。您可以继续使用它,只需确保您有正确的索引。也就是说,要获得这些更新的最佳性能,您应该有两个复合索引:

  • { _id: 1, teacherId: 1 }
  • { _id: 1, studentId: 1 }

从另一个角度来看,您应该重构数据。例如:

{
    _id: '...',
    users: [
        {
            userId: '...',
            userType: 'student',
            lastMessage: 'lorem ipsum'
        },
        {
            userId: '...',
            userType: 'teacher',
            lastMessage: 'dolor sit amet'
        }
    ]
}

这将允许您使用单个查询执行更新。

答案 1 :(得分:1)

您的数据结构有点奇怪,除非您有一个特定的业务案例,需要按照我建议的方式创建一个usertype,除非用户既可以是教师也可以是学生,然后保留您的结构。

$set{} param可以接受一个对象,我的建议是先做你的业务逻辑。在更新之前,您应该已经知道更新是针对教师还是学生 - 应该设置某种变量/认证级别以区分教师和学生。也许在成功登录回调后,您可以设置cookie /本地存储。无论如何 - 如果您拥有当前类型的用户,那么您可以更早地构建对象,因此根据用户类型创建具有所需属性的对象文字。  所以

if(student)
{ 
    var updateObj = { studentLastMsg: msg } 
}
else 
{ 
    var updateObj = { teacherLastMsg: msg }
}

然后传递$set{updateObj}的更新,我会将其设为一个代码段 - 在移动设备上