| CVE record lookup |
src/repositories/cveRepository.js:9 |
Callers read result.cve, check existence, clone, or build a new Cve model before writing. No caller saves the returned document. |
Add .lean() to this.collection.findOne().byCveId(id). |
| CVE-ID lookup |
src/repositories/cveIdRepository.js:9 |
Callers read state/owner/date fields or clone to plain JSON before findOneAndUpdate. No caller saves the returned document. |
Add .lean() to this.collection.findOne().byCveId(id). |
| Non-sequential CVE-ID available pool |
src/controller/cve-id.controller/cve-id.controller.js:696, :710, :736, :752 via BaseRepository.find |
The available IDs are only read by available[index].cve_id and removed from the local array with splice. No document methods are used. |
Allow BaseRepository.find to combine lean and limit, then call with { limit: availableLimit, lean: true }. Current branching in src/repositories/baseRepository.js:43 makes lean and limit mutually exclusive. |
| Registry org detail response |
src/repositories/baseOrgRepository.js:536 |
getOrg immediately calls data.toObject() and then only normalizes, enriches, filters, and returns response data. Related org lookups in the same method already use .lean(). |
Pass { ...options, lean: true } only inside getOrg, then remove the toObject() dependency. Do not make findOneByShortName/findOneByUUID lean by default because update flows save those docs. |
| Conversation list by target |
src/repositories/conversationRepository.js:51 |
Results are immediately converted with toObject(), filtered/redacted, and returned. Create/edit paths use separate hydrated queries for save(). |
Add .lean() to the ConversationModel.find(...) query and remove toObject(). |
| Conversation lookup by index |
src/repositories/conversationRepository.js:73 |
Used to get the conversation UUID/author for authorization before editConversation refetches the document for saving. |
Add .lean() to the indexed find(...).skip(...).limit(1) query. |
| Review object read-with-conversation helpers |
src/repositories/reviewObjectRepository.js:39, :96, :126 |
Each helper converts the review object to plain data, attaches conversations, filters new_review_data, and returns it. Update/approve/reject helpers are separate and still need hydrated docs. |
Add .lean() to those ReviewObjectModel.findOne(...) queries and remove toObject(). |
| User/org map expansion helpers |
src/repositories/baseUserRepository.js:207, src/repositories/baseOrgRepository.js:251 |
These are used by registry org _userMap building. Callers already tolerate plain objects with asPlainObject. |
Add .lean() to both projected find(...) queries. |
| Boolean/existence helpers |
src/repositories/baseOrgRepository.js:311, :332, :1211, :1240; src/repositories/baseUserRepository.js:89, :109, :328 |
These only return booleans, collision strings, role checks, or UUID arrays. |
Add projected .lean() or use exists() where only existence is needed. |
| Legacy CVE-ID map preload |
src/repositories/orgRepository.js:50, src/repositories/userRepository.js:64 used by src/controller/cve-id.controller/cve-id.controller.js:40 |
The CVE-ID list endpoint only builds maps from UUID, short name, username, and org UUID. |
Add .select(...) plus .lean() in these repository methods or add dedicated map-loading methods. |
| Audit reads |
src/repositories/auditRepository.js:89, :98, :106, :114 |
These return audit data directly or sort/slice history arrays. No save occurs on returned documents. |
Add .lean() and remove toObject() in findAllAuditDocuments. |
| Glossary reads |
src/repositories/glossaryRepository.js:9, :13 |
Controllers return JSON directly or use existence checks. No document methods are needed. |
Add .lean() before .exec(). |
Summary
Several read-only Mongoose query paths still hydrate full documents even though the code only reads fields, serializes data, or builds response objects. Adding
.lean()would reduce Mongoose hydration CPU/memory overhead and likely improve endpoint latency. This will not make MongoDB execute the query itself faster; it reduces Node/Mongoose post-query work.High-confidence candidates
src/repositories/cveRepository.js:9result.cve, check existence, clone, or build a newCvemodel before writing. No caller saves the returned document..lean()tothis.collection.findOne().byCveId(id).src/repositories/cveIdRepository.js:9findOneAndUpdate. No caller saves the returned document..lean()tothis.collection.findOne().byCveId(id).src/controller/cve-id.controller/cve-id.controller.js:696,:710,:736,:752viaBaseRepository.findavailable[index].cve_idand removed from the local array withsplice. No document methods are used.BaseRepository.findto combineleanandlimit, then call with{ limit: availableLimit, lean: true }. Current branching insrc/repositories/baseRepository.js:43makesleanandlimitmutually exclusive.src/repositories/baseOrgRepository.js:536getOrgimmediately callsdata.toObject()and then only normalizes, enriches, filters, and returns response data. Related org lookups in the same method already use.lean().{ ...options, lean: true }only insidegetOrg, then remove thetoObject()dependency. Do not makefindOneByShortName/findOneByUUIDlean by default because update flows save those docs.src/repositories/conversationRepository.js:51toObject(), filtered/redacted, and returned. Create/edit paths use separate hydrated queries forsave()..lean()to theConversationModel.find(...)query and removetoObject().src/repositories/conversationRepository.js:73editConversationrefetches the document for saving..lean()to the indexedfind(...).skip(...).limit(1)query.src/repositories/reviewObjectRepository.js:39,:96,:126new_review_data, and returns it. Update/approve/reject helpers are separate and still need hydrated docs..lean()to thoseReviewObjectModel.findOne(...)queries and removetoObject().src/repositories/baseUserRepository.js:207,src/repositories/baseOrgRepository.js:251_userMapbuilding. Callers already tolerate plain objects withasPlainObject..lean()to both projectedfind(...)queries.src/repositories/baseOrgRepository.js:311,:332,:1211,:1240;src/repositories/baseUserRepository.js:89,:109,:328.lean()or useexists()where only existence is needed.src/repositories/orgRepository.js:50,src/repositories/userRepository.js:64used bysrc/controller/cve-id.controller/cve-id.controller.js:40.select(...)plus.lean()in these repository methods or add dedicated map-loading methods.src/repositories/auditRepository.js:89,:98,:106,:114.lean()and removetoObject()infindAllAuditDocuments.src/repositories/glossaryRepository.js:9,:13.lean()before.exec().Not safe to change globally
Do not default these shared methods to lean without call-site options:
BaseOrgRepository.findOneByShortName,BaseOrgRepository.findOneByUUID,BaseUserRepository.findUserByUUID,BaseUserRepository.findOneByUsernameAndOrgShortname, and legacyUserRepository.findOneByUUID. Some update flows mutate returned docs and call.save(),.overwrite(),.pull(), or.addToSet().Suggested tests
Run targeted unit/integration coverage for CVE, CVE-ID reservation, registry org detail, registry user/org expansion, conversation, review object, audit, and glossary endpoints after implementation.