面试题答案
一键面试实现思路
- 在MongoDB Shell中,通过修改
prompt
函数来自定义提示信息。 - 在
prompt
函数内获取当前数据库集合中的文档数量。 - 将文档数量融入到自定义提示信息中并返回。
涉及MongoDB命令和编程逻辑
- 获取当前数据库集合文档数量:
- 使用
db.collection.countDocuments()
命令,db
代表当前数据库,collection
为具体集合名称。例如,如果当前集合为users
,则db.users.countDocuments()
可获取users
集合中的文档数量。
- 使用
- 自定义
prompt
函数:// 保存原有的prompt函数 var originalPrompt = prompt; prompt = function() { // 获取当前数据库名称 var dbName = db.getName(); // 获取当前集合名称(假设已选择一个集合,实际应用中可能需更复杂逻辑判断当前集合) var collectionName = db.getCollectionNames()[0]; // 获取文档数量 var docCount = db[collectionName].countDocuments(); // 构建新的提示信息 var newPrompt = '当前数据库: ' + dbName + ', 集合: ' + collectionName + ', 文档数量: ' + docCount + '> '; return newPrompt; };
高并发读写情况下可能遇到的问题及解决方案
- 问题:
- 数据一致性问题:在高并发读写时,获取文档数量的瞬间,其他写操作可能正在插入或删除文档,导致获取的数量并非实时准确。
- 性能问题:频繁获取文档数量会增加数据库负载,在高并发下可能影响整体读写性能。
- 解决方案:
- 针对数据一致性问题:
- 使用读隔离级别:例如设置为
majority
读关注,确保读取到的文档数量反映大多数节点的状态。在MongoDB 4.0及以上版本,可在读取操作时指定readConcern
选项,如db.collection.countDocuments({readConcern: {level: "majority"}})
。 - 使用变更流(Change Streams):监听集合的插入、更新和删除操作,实时更新文档数量缓存,这样在获取文档数量时直接从缓存读取,减少一致性问题。例如使用Node.js驱动监听变更流:
const { MongoClient } = require('mongodb'); const uri = "mongodb://localhost:27017"; const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true }); async function run() { try { await client.connect(); const db = client.db('test'); const collection = db.collection('users'); const changeStream = collection.watch(); let docCount = await collection.countDocuments(); changeStream.on('change', (change) => { if (change.operationType === 'insert') { docCount++; } else if (change.operationType === 'delete') { docCount--; } // 这里可以将docCount用于更新缓存等操作 }); } finally { await client.close(); } } run().catch(console.dir);
- 使用读隔离级别:例如设置为
- 针对性能问题:
- 缓存机制:将获取的文档数量进行缓存,设置合理的缓存过期时间。在过期时间内,提示信息直接从缓存获取文档数量,减少对数据库的查询次数。例如在应用层使用Redis缓存,获取文档数量时先从Redis读取,若缓存不存在或过期,再从MongoDB获取并更新缓存。
- 异步操作:在自定义
prompt
函数中,使用异步方式获取文档数量,避免阻塞其他操作。例如在JavaScript中使用async/await
语法,让获取文档数量的操作在后台执行,不影响其他读写操作。var originalPrompt = prompt; prompt = async function() { var dbName = db.getName(); var collectionName = db.getCollectionNames()[0]; var docCount = await db[collectionName].countDocuments(); var newPrompt = '当前数据库: ' + dbName + ', 集合: ' + collectionName + ', 文档数量: ' + docCount + '> '; return newPrompt; };
- 针对数据一致性问题: