面试题答案
一键面试- 判断索引对更新操作是否有帮助:
- 更新条件:如果更新操作的
$match
条件(用于定位要更新的文档)能够利用索引,那么索引对更新操作有帮助。例如,如果有一个集合users
,包含字段name
和age
,如果更新操作为db.users.updateMany({name: "John"}, {$set: {age: 30}})
,若name
字段上有索引,那么这个索引就能加速定位要更新的文档,对更新操作有帮助。因为MongoDB可以通过索引快速找到name
为John
的文档,而不需要全表扫描。 - 覆盖索引:当更新操作不仅能利用索引定位文档,而且更新所涉及的字段都包含在索引中(覆盖索引)时,索引的帮助更大。例如
db.users.updateMany({name: "John"}, {$inc: {loginCount: 1}})
,如果name
和loginCount
都在一个复合索引中,那么MongoDB可以直接在索引结构上完成更新,而不需要再去磁盘读取文档,大大提高更新效率。
- 更新条件:如果更新操作的
- 常见更新操作场景下索引的作用:
- 单文档更新:
- 场景:假设我们有一个
products
集合,每个文档代表一个产品,包含productId
、price
等字段。db.products.updateOne({productId: "P001"}, {$set: {price: 9.99}})
。 - 索引作用:如果
productId
字段上有索引,MongoDB能迅速定位到productId
为P001
的文档进行更新。如果没有索引,就需要遍历整个products
集合来查找该文档,在集合数据量较大时,效率会很低。
- 场景:假设我们有一个
- 多文档更新:
- 场景:在
orders
集合中,包含customerId
、status
等字段,我们要将所有customerId
为C001
且status
为"pending"
的订单状态更新为"processing"
,操作如下db.orders.updateMany({customerId: "C001", status: "pending"}, {$set: {status: "processing"}})
。 - 索引作用:如果在
customerId
和status
字段上建立了复合索引(顺序为customerId
在前,status
在后),MongoDB可以利用该索引快速定位到符合条件的订单文档进行更新。复合索引可以减少全表扫描的范围,提高多文档更新的效率。
- 场景:在
- 数组元素更新:
- 场景:在
students
集合中,每个文档包含一个scores
数组,记录学生的各科成绩,我们要将studentId
为S001
的学生的数学成绩(假设数组中第一个元素为数学成绩)增加5分,操作如下db.students.updateOne({studentId: "S001"}, {$inc: {"scores.0": 5}})
。 - 索引作用:如果
studentId
字段有索引,能快速定位到目标学生文档。虽然这里是对数组元素操作,但通过studentId
索引定位文档是第一步,为后续数组元素更新奠定基础。若没有studentId
索引,定位学生文档会很耗时,尤其在集合数据量庞大时。
- 场景:在
- 单文档更新: