MST

星途 面试题库

面试题:MongoDB数组更新的复杂操作

假设有集合documents,其中文档结构为{ _id: ObjectId('5f9075a406290d46c6c77c0b'), scores: [ { subject: 'Math', score: 85 }, { subject: 'Science', score: 90 } ] }。现在要将Math的成绩提高5分,并且如果文档中没有'History'科目的成绩记录,要添加一条{ subject: 'History', score: 0 }的记录。请写出对应的更新操作语句,并解释其中使用的操作符原理。
42.3万 热度难度
数据库MongoDB

知识考点

AI 面试

面试题答案

一键面试

在MongoDB中,可以使用以下更新操作语句:

db.documents.updateOne(
    {},
    [
        {
            $addFields: {
                scores: {
                    $map: {
                        input: "$scores",
                        as: "score",
                        in: {
                            $cond: [
                                { $eq: ["$$score.subject", "Math"] },
                                { subject: "Math", score: { $add: ["$$score.score", 5] } },
                                "$$score"
                            ]
                        }
                    }
                }
            }
        },
        {
            $addFields: {
                scores: {
                    $cond: [
                        { $not: { $in: ["History", "$scores.subject"] } },
                        {
                            $concatArrays: ["$scores", [ { subject: "History", score: 0 } ] ]
                        },
                        "$scores"
                    ]
                }
            }
        }
    ],
    { multi: true }
);

操作符原理解释:

  1. $addFields:用于向文档中添加新的字段或替换现有字段的值。这里使用了两次 $addFields 操作符,分别对 scores 数组进行修改。
  2. $map:对数组的每个元素应用指定的表达式,并返回新的数组。在第一个 $addFields 中,$map 遍历 scores 数组,检查每个元素的 subject 是否为 Math。如果是,则将该元素的 score 增加5分;否则,保持该元素不变。
  3. $cond:条件操作符,根据条件表达式的值返回不同的结果。在 $map 中,$cond 用于判断当前 scoresubject 是否为 Math,并根据结果返回修改后的 score 或原始 score。在第二个 $addFields 中,$cond 用于判断 History 是否在 scores 数组的 subject 中。如果不在,则将 { subject: "History", score: 0 } 添加到 scores 数组中;否则,保持 scores 数组不变。
  4. $concatArrays:用于连接多个数组。在第二个 $addFields 中,当 History 不在 scores 数组的 subject 中时,$concatArrays 将原 scores 数组和 [ { subject: "History", score: 0 } ] 连接起来,形成新的 scores 数组。
  5. $not:逻辑操作符,对表达式的结果取反。在第二个 $addFields 中,$not 用于判断 History 不在 scores 数组的 subject 中。
  6. $in:检查一个值是否在数组中。在第二个 $addFields 中,$in 用于检查 History 是否在 scores 数组的 subject 中。

最后,{ multi: true } 选项确保对集合中的所有文档执行更新操作。如果不设置该选项,默认只更新第一个匹配的文档。