Skip to content

Commit

Permalink
updateSortingOrder supports re-sorting in place (#293)
Browse files Browse the repository at this point in the history
  • Loading branch information
zichongkao committed May 19, 2023
1 parent 8e50ebc commit 2589e6b
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 7 deletions.
26 changes: 21 additions & 5 deletions src/model/MutableAreaDataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -368,9 +368,25 @@ export default class MutableAreaDataSource extends AreaDataSource {
const doUpdate = async (session: ClientSession, user: MUUID, input: UpdateSortingOrderType[]): Promise<string[]> => {
const opType = OperationType.orderAreas
const change = await changelogDataSource.create(session, user, opType)
const updates: any[] = []
let expectedOpCount = input.length

// Clear existing indices so we can re-order without running into duplicate key errors.
if (input.some(i => i.leftRightIndex >= 0)) {
updates.push({
updateMany: {
filter: { 'metadata.area_id': { $in: input.map(i => muuid.from(i.areaId)) } },
update: {
$set: { 'metadata.leftRightIndex': -1 }
// Don't record change since this is an intermediate step.
}
}
})
expectedOpCount = expectedOpCount * 2
}

const bulkData = input.map(({ areaId, leftRightIndex }, index) => (
{
input.forEach(({ areaId, leftRightIndex }, index) => {
updates.push({
updateOne: {
filter: { 'metadata.area_id': muuid.from(areaId) },
update: {
Expand All @@ -387,11 +403,11 @@ export default class MutableAreaDataSource extends AreaDataSource {
}
}
})
)
})

const rs = (await this.areaModel.bulkWrite(bulkData, { session })).toJSON()
const rs = (await this.areaModel.bulkWrite(updates, { session })).toJSON()

if (rs.ok === 1 && rs.nMatched === rs.nModified && rs.nMatched === input.length) {
if (rs.ok === 1 && rs.nMatched === rs.nModified && rs.nMatched === expectedOpCount) {
return input.map(item => item.areaId)
} else {
throw new Error(`Expect to update ${input.length} areas but found ${rs.nMatched}.`)
Expand Down
17 changes: 15 additions & 2 deletions src/model/__tests__/updateAreas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,13 +277,26 @@ describe('Areas', () => {
})
}))

// Able to overwrite existing leftRightIndices without duplicate key errors
const change3: UpdateSortingOrderType = {
areaId: a1.metadata.area_id.toUUID().toString(),
leftRightIndex: 9
}
const change4: UpdateSortingOrderType = {
areaId: a2.metadata.area_id.toUUID().toString(),
leftRightIndex: 10
}

await expect(areas.updateSortingOrder(testUser, [change3, change4])).resolves.toStrictEqual(
[a1.metadata.area_id.toUUID().toString(), a2.metadata.area_id.toUUID().toString()])

// Make sure we can't have duplicate leftToRight indices >= 0
await expect(
areas.updateSortingOrder(testUser, [{ ...change1, leftRightIndex: change2.leftRightIndex }]))
areas.updateSortingOrder(testUser, [{ ...change3, leftRightIndex: change4.leftRightIndex }]))
.rejects.toThrowError(/E11000/)

// But we can have duplicate indices < 0 to indicate unsorted
await areas.updateSortingOrder(testUser,
[{ ...change1, leftRightIndex: -1 }, { ...change2, leftRightIndex: -1 }])
[{ ...change3, leftRightIndex: -1 }, { ...change4, leftRightIndex: -1 }])
})
})

0 comments on commit 2589e6b

Please sign in to comment.