-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Migration to add age bucketing field to cases schema #2670
- Loading branch information
Showing
2 changed files
with
79 additions
and
1 deletion.
There are no files selected for viewing
77 changes: 77 additions & 0 deletions
77
data-serving/scripts/setup-db/migrations/20220420100113-add-age-buckets.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/* | ||
* We need to ensure that ages are bucketed within five-year brackets, except for infants (below 1 year) | ||
* to improve the protection against deanonymisation in the case database. In this migration I create an | ||
* ageBuckets collection which represents an enumeration of the age ranges 0, 1-5, 6-10, 11-15, ..., 116-120. | ||
* | ||
* I also allow the cases collection documents to have an array of unique objectIDs in the 'demographics.ageBuckets' | ||
* property. That means that each case can link to zero or more elements in the enumeration. Here are some examples of | ||
* how that will work: | ||
* | ||
* case has no age specified: ageBuckets = [] | ||
* case has exact age 18: ageBuckets = [(16-20)._id] | ||
* case has range 18-24: ageBuckets = [(16-20)._id, (21-25)._id] | ||
*/ | ||
|
||
const ageBucketSchema = { | ||
bsonType: 'array', | ||
uniqueItems: true, | ||
items: { | ||
bsonType: "objectId", | ||
} | ||
}; | ||
|
||
module.exports = { | ||
async up(db, client) { | ||
await db.createCollection("ageBuckets", { | ||
validator: { | ||
$jsonSchema: { | ||
"bsonType": "object", | ||
"additionalProperties": false, | ||
"required": ["start", "end"], | ||
"properties": { | ||
"_id": { | ||
"bsonType": "objectId", | ||
}, | ||
"start": { | ||
"bsonType": "number", | ||
"minimum": 0, | ||
"maximum": 116 | ||
}, | ||
"end": { | ||
"bsonType": "number", | ||
"minimum": 0, | ||
"maximum": 120 | ||
} | ||
} | ||
} | ||
} | ||
}); | ||
|
||
const ageBuckets = db.collection('ageBuckets'); | ||
await ageBuckets.insertOne({ | ||
start: 0, | ||
end: 0, | ||
}); | ||
for(let start = 1; start <= 116; start += 5) { | ||
const end = start + 4; | ||
await ageBuckets.insertOne({ | ||
start, | ||
end, | ||
}); | ||
} | ||
|
||
let res = await db.command({listCollections: undefined, filter: {name: 'cases'}}); | ||
let schema = res.cursor.firstBatch[0].options.validator.$jsonSchema; | ||
schema.properties.demographics.properties.ageBuckets = ageBucketSchema; | ||
await db.command({ collMod: 'cases', validator:{ $jsonSchema: schema } } ); | ||
}, | ||
|
||
async down(db, client) { | ||
let res = await db.command({listCollections: undefined, filter: {name: 'cases'}}); | ||
let schema = res.cursor.firstBatch[0].options.validator.$jsonSchema; | ||
delete schema.properties.demographics.properties.ageBuckets; | ||
await db.command( { collMod: 'cases', validator:{ $jsonSchema: schema } } ); | ||
|
||
await db.collection('ageBuckets').drop(); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
# Mongodb schema validators | ||
|
||
This directory contains schema validators and index files for the various collections stored in mongodb. | ||
These are the _initial_ state of the database: modifications are made via migrations. See the `mongo-migrations` folder for more information. | ||
These are the _initial_ state of the database: do not make changes here, as they won't make any difference in production! | ||
Modifications are made via migrations: every new change requires a new migration. See the `migrations` folder for more information. |