Node.js中给MongoDB查询文档添加saved标记失败问题求助
问题分析与解决
原代码与问题现象
原代码尝试对比documents和savedDocuments集合的文档ID,给匹配的文档标记saved: true,不匹配的标记saved: false,但最终结果是saved字段被添加到了数组对象本身,而非每个文档内部,且结果不符合预期:
let collection = database.collection('documents') let savedDocumentsCollection = database.collection('savedDocuments') let doc = await collection.find().toArray() let saved_documents = await savedDocumentsCollection.find({username: req.session.username}).toArray() let document_ids = [] for (var i = 0; i < doc.length; i++) { document_ids.push(doc[i].id) } for (var x = 0; x < saved_documents.length; x++) { for(let val of document_ids) { if (val == saved_documents[x].id) { doc = { ...doc, saved: true } // console.log(true) } else { doc = { ...doc, saved: false } // console.log(false) } } } console.log(doc)
执行后输出示例:
{ '0': { _id: new ObjectId("635f3c3d79dffde472e69287"), course_code: 'xxxxx', name_of_document: 'doc 1', name_of_s: 'COMPANY', url: 'url', uploadedBy: 'John.doe@gmail.com', date: 2022-10-31T03:08:45.123Z, id: '2ac3c' }, '1': { course_code: 'xxxxx', name_of_document: 'doc 2', name_of_s: 'COMPANY', url: 'url', uploadedBy: 'John.doe@gmail.com', date: 2022-10-31T03:14:40.722Z, id: 'fursr' }, saved: false }
错误原因
- 操作对象错误:
doc是toArray()返回的数组,你直接用doc = {...doc, saved: true}会把数组转成普通对象,并且把saved字段加到这个顶层对象上,而非数组里的单个文档元素。 - 循环逻辑混乱:嵌套循环会反复覆盖顶层对象的
saved属性,最后只会保留最后一次循环的结果,根本没处理到数组里的每个文档。 - 效率低下:多层循环对比ID的时间复杂度高,不如用集合(Set)实现快速查找。
修正后的代码
let collection = database.collection('documents') let savedDocumentsCollection = database.collection('savedDocuments') // 获取所有文档数组 let docs = await collection.find().toArray() // 获取当前用户保存的文档,提取ID存入Set(快速查找) let savedDocs = await savedDocumentsCollection.find({username: req.session.username}).toArray() let savedDocIds = new Set(savedDocs.map(item => item.id)) // 遍历每个文档,添加saved标记 docs = docs.map(docItem => { return { ...docItem, saved: savedDocIds.has(docItem.id) } }) console.log(docs)
解释
- 用Set存储已保存ID:
Set的has()方法查找时间复杂度为O(1),比循环遍历高效得多。 - 遍历数组元素:用
map()方法遍历每个文档对象,给每个对象单独添加saved字段,不会改变数组结构,每个文档都会带上正确的匹配标记。 - 变量命名更清晰:把原变量
doc改成docs(复数),更符合数组的语义,避免混淆。
内容的提问来源于stack exchange,提问作者bobthebuilder
相关产品推荐
相关产品推荐

