如何高效迭代JSON对象并基于输入过滤MongoDB返回数据?
高性能匹配MongoDB返回数据中的EventId方案
我把数据存在MongoDB里,想找类似Java流处理的功能没找到。现在需要从数据库返回的6万行JSON数据中,匹配服务输入的eventId,用传统三重循环处理时,输入20个eventId就要耗时23秒,求最优处理方案。
数据库返回数据
[ { "eventList": [ { "eventId": "1,2,3", "eventType": "1" }, { "eventId": "4,5,6", "eventType": "2" } ] }, { "eventList": [ { "eventId": "7,8,9", "eventType": "3" } ] } ]
服务输入参数
{ "eventId": [ "1", "2" ] }
原实现代码
for (let i = 0; i < request.eventId.length; i++) { let eventId = request.eventId[i]; for (let j = 0; j < response.length; j++) { for (let k = 0; k < response[j].eventList.length; k++) { if (response[j].eventList[k].eventId.includes(eventId)) { console.log("matches"); } } } }
优化方案
内存层面优化:用哈希集合降低查找复杂度
原代码三重循环的时间复杂度是O(M*N*K)(M为输入eventId数量,N为返回数据条数,K为每个eventList的长度),6万条数据下这个复杂度会导致性能急剧下降。优化思路是把输入的eventId存入Set(查找时间O(1)),遍历数据库返回数据时直接拆分eventId字符串匹配,把复杂度降到O(N*K + M):
// 把输入的eventId转成Set,实现O(1)快速查找 const targetEventIds = new Set(request.eventId); const matchedEvents = []; // 遍历数据库返回的每一项 for (const dataItem of response) { // 遍历当前项的eventList for (const event of dataItem.eventList) { // 拆分逗号分隔的eventId为数组 const currentEventIds = event.eventId.split(','); // 检查是否有匹配的id const isMatched = currentEventIds.some(id => targetEventIds.has(id)); if (isMatched) { matchedEvents.push(event); // 可按需保存匹配结果 console.log("matches"); } } }
根源优化:将匹配逻辑放在数据库层面(最优解)
如果可以修改MongoDB的文档结构,建议把eventId字段从逗号分隔的字符串改成数组类型(比如"eventId": ["1","2","3"]),这样直接用MongoDB的$in操作符在数据库端完成匹配,不需要把6万条数据拉到内存处理,性能提升最明显:
修改后的文档结构示例:
{ "eventList": [ { "eventId": ["1","2","3"], "eventType": "1" } ] }
对应的查询语句:
// 直接在数据库中过滤匹配的数据 db.collection.find({ "eventList.eventId": { $in: request.eventId } })
数据库会利用索引快速定位匹配数据,避免大量数据传输和内存处理,这是效率最高的方案。
内容的提问来源于stack exchange,提问作者gautham
相关产品推荐
相关产品推荐

