[web] remove unnecessary filtering of rootFolder (#31585)

11 years ago, the db.projects collection was storing doc lines in the
file-tree/rootFolder. Any operations on the project that did not need
those lines were benefitting from excluding all those entries from the
file-tree. These days, the verbose exclusions are not useful anymore and
merely add load on mongo.

REF: 9805c6a9ff
GitOrigin-RevId: 89f544688934c1ed1ca98877ffbe8baefe66c126
This commit is contained in:
Jakob Ackermann
2026-02-18 13:06:27 +01:00
committed by Copybot
parent 13e03fafa2
commit cb0266035d
12 changed files with 29 additions and 133 deletions
@@ -77,8 +77,7 @@ async function joinProject(req, res, next) {
}
async function _buildJoinProjectView(req, projectId, userId) {
const project =
await ProjectGetter.promises.getProjectWithoutDocLines(projectId)
const project = await ProjectGetter.promises.getProject(projectId)
if (project == null) {
throw new Errors.NotFoundError('project not found')
}
@@ -79,8 +79,9 @@ function getAllEntitiesFromProject(project) {
}
async function getAllDocPathsFromProjectById(projectId) {
const project =
await ProjectGetter.promises.getProjectWithoutDocLines(projectId)
const project = await ProjectGetter.promises.getProject(projectId, {
rootFolder: 1,
})
if (project == null) {
throw new Errors.NotFoundError('no project')
}
@@ -120,8 +121,9 @@ async function getDoc(projectId, docId, options = {}) {
* @param {ObjectId | string} docId
*/
async function getDocPathByProjectIdAndDocId(projectId, docId) {
const project =
await ProjectGetter.promises.getProjectWithoutDocLines(projectId)
const project = await ProjectGetter.promises.getProject(projectId, {
rootFolder: 1,
})
if (project == null) {
throw new Errors.NotFoundError('no project')
}
@@ -165,8 +167,9 @@ async function getDocPathFromProjectByDocId(project, docId) {
}
async function _getAllFolders(projectId) {
const project =
await ProjectGetter.promises.getProjectWithoutDocLines(projectId)
const project = await ProjectGetter.promises.getProject(projectId, {
rootFolder: 1,
})
if (project == null) {
throw new Errors.NotFoundError('no project')
@@ -269,8 +269,10 @@ async function mkdirp(projectId, path, userId, options = {}) {
// to make matching case-sensitive
const folders = path.split('/').filter(folder => folder.length !== 0)
const project =
await ProjectGetter.promises.getProjectWithOnlyFolders(projectId)
const project = await ProjectGetter.promises.getProjectWithoutLock(
projectId,
{ rootFolder: 1 }
)
if (path === '/') {
return { newFolders: [], folder: project.rootFolder[0] }
}
@@ -11,25 +11,6 @@ import CollaboratorsGetter from '../Collaborators/CollaboratorsGetter.mjs'
const { normalizeQuery } = Mongo
const ProjectGetter = {
EXCLUDE_DEPTH: 8,
async getProjectWithoutDocLines(projectId) {
const excludes = {}
for (let i = 1; i <= ProjectGetter.EXCLUDE_DEPTH; i++) {
excludes[`rootFolder${Array(i).join('.folders')}.docs.lines`] = 0
}
return await ProjectGetter.getProject(projectId, excludes)
},
async getProjectWithOnlyFolders(projectId) {
const excludes = {}
for (let i = 1; i <= ProjectGetter.EXCLUDE_DEPTH; i++) {
excludes[`rootFolder${Array(i).join('.folders')}.docs`] = 0
excludes[`rootFolder${Array(i).join('.folders')}.fileRefs`] = 0
}
return await ProjectGetter.getProject(projectId, excludes)
},
async getProject(projectId, projection = {}) {
if (projectId == null) {
throw new Error('no project id provided')
@@ -146,8 +146,10 @@ async function ensureRootDocumentIsSet(projectId) {
* @param {ObjectId | string} projectId
*/
async function ensureRootDocumentIsValid(projectId) {
const project =
await ProjectGetter.promises.getProjectWithoutDocLines(projectId)
const project = await ProjectGetter.promises.getProject(projectId, {
rootFolder: 1,
rootDoc_id: 1,
})
if (!project) {
throw new Error('project not found')
}
@@ -131,7 +131,7 @@ describe('EditorHttpController', function () {
}
ctx.ProjectGetter = {
promises: {
getProjectWithoutDocLines: sinon.stub().resolves(ctx.project),
getProject: sinon.stub().resolves(ctx.project),
},
}
ctx.ProjectEditorHandler = {
@@ -461,7 +461,7 @@ describe('EditorHttpController', function () {
describe('when project is not found', function () {
beforeEach(async function (ctx) {
ctx.ProjectGetter.promises.getProjectWithoutDocLines.resolves(null)
ctx.ProjectGetter.promises.getProject.resolves(null)
await new Promise(resolve => {
ctx.next.callsFake(() => resolve())
ctx.EditorHttpController.joinProject(ctx.req, ctx.res, ctx.next)
@@ -34,7 +34,6 @@ describe('ProjectDetailsHandler', function () {
}
ctx.ProjectGetter = {
promises: {
getProjectWithoutDocLines: sinon.stub().resolves(ctx.project),
getProject: sinon.stub().resolves(ctx.project),
findAllUsersProjects: sinon.stub().resolves({
owned: [],
@@ -105,9 +105,7 @@ describe('ProjectEntityHandler', function () {
],
},
]
ctx.ProjectGetter.promises.getProjectWithoutDocLines = sinon
.stub()
.resolves(ctx.project)
ctx.ProjectGetter.promises.getProject = sinon.stub().resolves(ctx.project)
})
describe('getAllDocs', function () {
@@ -253,7 +251,7 @@ describe('ProjectEntityHandler', function () {
})
it('should get the project without the docs lines', function (ctx) {
ctx.ProjectGetter.promises.getProjectWithoutDocLines
ctx.ProjectGetter.promises.getProject
.calledWith(projectId)
.should.equal(true)
})
@@ -317,9 +315,7 @@ describe('ProjectEntityHandler', function () {
],
},
]
ctx.ProjectGetter.promises.getProjectWithoutDocLines = sinon
.stub()
.resolves(ctx.project)
ctx.ProjectGetter.promises.getProject = sinon.stub().resolves(ctx.project)
})
describe('getAllDocs', function () {
@@ -185,7 +185,7 @@ describe('ProjectEntityMongoUpdateHandler', function () {
.stub()
.withArgs(ctx.project._id)
.resolves(ctx.project),
getProjectWithOnlyFolders: sinon.stub().resolves(ctx.project),
getProject: sinon.stub().resolves(ctx.project),
},
}
@@ -109,7 +109,6 @@ describe('ProjectEntityUpdateHandler', function () {
ctx.ProjectGetter = {
promises: {
getProject: sinon.stub(),
getProjectWithoutDocLines: sinon.stub(),
},
}
ctx.ProjectLocator = {
@@ -89,87 +89,6 @@ describe('ProjectGetter', function () {
ctx.ProjectGetter = (await import(modulePath)).default
})
describe('getProjectWithoutDocLines', function () {
beforeEach(function (ctx) {
ctx.ProjectGetter.promises.getProject = sinon.stub().resolves()
})
describe('passing an id', function () {
beforeEach(async function (ctx) {
await ctx.ProjectGetter.promises.getProjectWithoutDocLines(
ctx.project._id
)
})
it('should call find with the project id', function (ctx) {
ctx.ProjectGetter.promises.getProject
.calledWith(ctx.project._id)
.should.equal(true)
})
it('should exclude the doc lines', function (ctx) {
const excludes = {
'rootFolder.docs.lines': 0,
'rootFolder.folders.docs.lines': 0,
'rootFolder.folders.folders.docs.lines': 0,
'rootFolder.folders.folders.folders.docs.lines': 0,
'rootFolder.folders.folders.folders.folders.docs.lines': 0,
'rootFolder.folders.folders.folders.folders.folders.docs.lines': 0,
'rootFolder.folders.folders.folders.folders.folders.folders.docs.lines': 0,
'rootFolder.folders.folders.folders.folders.folders.folders.folders.docs.lines': 0,
}
ctx.ProjectGetter.promises.getProject
.calledWith(ctx.project._id, excludes)
.should.equal(true)
})
})
})
describe('getProjectWithOnlyFolders', function () {
beforeEach(function (ctx) {
ctx.ProjectGetter.promises.getProject = sinon.stub().resolves()
})
describe('passing an id', function () {
beforeEach(async function (ctx) {
await ctx.ProjectGetter.promises.getProjectWithOnlyFolders(
ctx.project._id
)
})
it('should call find with the project id', function (ctx) {
ctx.ProjectGetter.promises.getProject
.calledWith(ctx.project._id)
.should.equal(true)
})
it('should exclude the docs and files lines', function (ctx) {
const excludes = {
'rootFolder.docs': 0,
'rootFolder.fileRefs': 0,
'rootFolder.folders.docs': 0,
'rootFolder.folders.fileRefs': 0,
'rootFolder.folders.folders.docs': 0,
'rootFolder.folders.folders.fileRefs': 0,
'rootFolder.folders.folders.folders.docs': 0,
'rootFolder.folders.folders.folders.fileRefs': 0,
'rootFolder.folders.folders.folders.folders.docs': 0,
'rootFolder.folders.folders.folders.folders.fileRefs': 0,
'rootFolder.folders.folders.folders.folders.folders.docs': 0,
'rootFolder.folders.folders.folders.folders.folders.fileRefs': 0,
'rootFolder.folders.folders.folders.folders.folders.folders.docs': 0,
'rootFolder.folders.folders.folders.folders.folders.folders.fileRefs': 0,
'rootFolder.folders.folders.folders.folders.folders.folders.folders.docs': 0,
'rootFolder.folders.folders.folders.folders.folders.folders.folders.fileRefs': 0,
}
ctx.ProjectGetter.promises.getProject
.calledWith(ctx.project._id, excludes)
.should.equal(true)
})
})
})
describe('getProject', function () {
describe('without projection', function () {
describe('with project id', function () {
@@ -587,9 +587,7 @@ describe('ProjectRootDocManager', function () {
beforeEach(function (ctx) {
ctx.project = {}
ctx.ProjectGetter.promises.getProject = sinon.stub().resolves(ctx.project)
ctx.ProjectGetter.promises.getProjectWithoutDocLines = sinon
.stub()
.resolves(ctx.project)
ctx.ProjectGetter.promises.getProject = sinon.stub().resolves(ctx.project)
ctx.ProjectEntityUpdateHandler.promises.setRootDoc = sinon
.stub()
.resolves()
@@ -614,7 +612,7 @@ describe('ProjectRootDocManager', function () {
})
it('should find the project without doc lines', function (ctx) {
ctx.ProjectGetter.promises.getProjectWithoutDocLines
ctx.ProjectGetter.promises.getProject
.calledWith(ctx.project_id)
.should.equal(true)
})
@@ -638,7 +636,7 @@ describe('ProjectRootDocManager', function () {
})
it('should find the project without doc lines', function (ctx) {
ctx.ProjectGetter.promises.getProjectWithoutDocLines
ctx.ProjectGetter.promises.getProject
.calledWith(ctx.project_id)
.should.equal(true)
})
@@ -665,7 +663,7 @@ describe('ProjectRootDocManager', function () {
})
it('should find the project without doc lines', async function (ctx) {
ctx.ProjectGetter.promises.getProjectWithoutDocLines
ctx.ProjectGetter.promises.getProject
.calledWith(ctx.project_id)
.should.equal(true)
})
@@ -679,9 +677,7 @@ describe('ProjectRootDocManager', function () {
describe('when the project does not exist', function () {
beforeEach(async function (ctx) {
ctx.ProjectGetter.promises.getProjectWithoutDocLines = sinon
.stub()
.resolves(null)
ctx.ProjectGetter.promises.getProject = sinon.stub().resolves(null)
})
it('should reject', async function (ctx) {