From 919a4157efdaa7c37891c8a978c2f1faf66888f3 Mon Sep 17 00:00:00 2001 From: Kelly Moran Date: Mon, 22 Jun 2020 15:11:16 -0400 Subject: [PATCH] Add genomeSequences field to schema per spec --- .../data-service/schemas/cases.schema.json | 31 ++++++++++++++ data-serving/data-service/src/model/case.ts | 6 +++ .../data-service/src/model/genome-sequence.ts | 21 ++++++++++ .../test/model/data/case.full.json | 10 +++++ .../test/model/data/genome-sequence.full.json | 8 ++++ .../model/data/genome-sequence.minimal.json | 1 + .../test/model/genome-sequence.test.ts | 42 +++++++++++++++++++ data-serving/samples/cases.json | 12 ++++++ 8 files changed, 131 insertions(+) create mode 100644 data-serving/data-service/src/model/genome-sequence.ts create mode 100644 data-serving/data-service/test/model/data/genome-sequence.full.json create mode 100644 data-serving/data-service/test/model/data/genome-sequence.minimal.json create mode 100644 data-serving/data-service/test/model/genome-sequence.test.ts diff --git a/data-serving/data-service/schemas/cases.schema.json b/data-serving/data-service/schemas/cases.schema.json index c6b0a6184..75785a08d 100644 --- a/data-serving/data-service/schemas/cases.schema.json +++ b/data-serving/data-service/schemas/cases.schema.json @@ -73,6 +73,37 @@ } } }, + "genomeSequences": { + "bsonType": "array", + "uniqueItems": true, + "items": { + "bsonType": "object", + "additionalProperties": false, + "properties": { + "_id": { + "bsonType": "objectId" + }, + "sampleCollectionDate": { + "bsonType": "date" + }, + "repositoryUrl": { + "bsonType": "string" + }, + "sequenceId": { + "bsonType": "string" + }, + "sequenceName": { + "bsonType": "string" + }, + "sequenceLength": { + "bsonType": "int" + }, + "notes": { + "bsonType": "string" + } + } + } + }, "location": { "bsonType": "object", "additionalProperties": false, diff --git a/data-serving/data-service/src/model/case.ts b/data-serving/data-service/src/model/case.ts index beef28b4a..17a08ee8b 100644 --- a/data-serving/data-service/src/model/case.ts +++ b/data-serving/data-service/src/model/case.ts @@ -2,6 +2,10 @@ import { CaseReferenceDocument, caseReferenceSchema } from './case-reference'; import { DemographicsDocument, demographicsSchema } from './demographics'; import { DictionaryDocument, dictionarySchema } from './dictionary'; import { EventDocument, eventSchema } from './event'; +import { + GenomeSequenceDocument, + genomeSequenceSchema, +} from './genome-sequence'; import { LocationDocument, locationSchema } from './location'; import { PathogenDocument, pathogenSchema } from './pathogen'; import { @@ -27,6 +31,7 @@ const caseSchema = new mongoose.Schema( message: 'Must include an event with name "confirmed"', }, }, + genomeSequences: [genomeSequenceSchema], importedCase: {}, location: locationSchema, revisionMetadata: { @@ -68,6 +73,7 @@ type CaseDocument = mongoose.Document & { caseReference: CaseReferenceDocument; demographics: DemographicsDocument; events: [EventDocument]; + genomeSequences: [GenomeSequenceDocument]; importedCase: {}; location: LocationDocument; revisionMetadata: RevisionMetadataDocument; diff --git a/data-serving/data-service/src/model/genome-sequence.ts b/data-serving/data-service/src/model/genome-sequence.ts new file mode 100644 index 000000000..e5daf4de8 --- /dev/null +++ b/data-serving/data-service/src/model/genome-sequence.ts @@ -0,0 +1,21 @@ +import { dateFieldInfo } from './date'; +import mongoose from 'mongoose'; +import { positiveIntFieldInfo } from './positive-int'; + +export const genomeSequenceSchema = new mongoose.Schema({ + sampleCollectionDate: dateFieldInfo, + repositoryUrl: String, + sequenceId: String, + sequenceName: String, + sequenceLength: positiveIntFieldInfo, + notes: String, +}); + +export type GenomeSequenceDocument = mongoose.Document & { + sampleCollectionDate: Date; + repositoryUrl: string; + sequenceId: string; + sequenceName: string; + sequenceLength: number; + notes: string; +}; diff --git a/data-serving/data-service/test/model/data/case.full.json b/data-serving/data-service/test/model/data/case.full.json index 82cb043ac..6cd8adc5e 100644 --- a/data-serving/data-service/test/model/data/case.full.json +++ b/data-serving/data-service/test/model/data/case.full.json @@ -13,6 +13,16 @@ "nationality": "Swedish", "ethnicity": "Other" }, + "genomeSequences": [ + { + "sampleCollectionDate": "2019-12-30", + "repositoryUrl": "https://www.ncbi.nlm.nih.gov/nuccore/NC_045512", + "sequenceId": "NC_045512.2", + "sequenceName": "Severe acute respiratory syndrome coronavirus 2 isolate Wuhan-Hu-1, complete genome", + "sequenceLength": 33000, + "notes": "The reference sequence is identical to MN908947." + } + ], "location": { "country": "France", "administrativeAreaLevel1": "Île-de-France", diff --git a/data-serving/data-service/test/model/data/genome-sequence.full.json b/data-serving/data-service/test/model/data/genome-sequence.full.json new file mode 100644 index 000000000..d9d7d1386 --- /dev/null +++ b/data-serving/data-service/test/model/data/genome-sequence.full.json @@ -0,0 +1,8 @@ +{ + "sampleCollectionDate": "2019-12-30", + "repositoryUrl": "https://www.ncbi.nlm.nih.gov/nuccore/NC_045512", + "sequenceId": "NC_045512.2", + "sequenceName": "Severe acute respiratory syndrome coronavirus 2 isolate Wuhan-Hu-1, complete genome", + "sequenceLength": 33000, + "notes": "The reference sequence is identical to MN908947." +} \ No newline at end of file diff --git a/data-serving/data-service/test/model/data/genome-sequence.minimal.json b/data-serving/data-service/test/model/data/genome-sequence.minimal.json new file mode 100644 index 000000000..9e26dfeeb --- /dev/null +++ b/data-serving/data-service/test/model/data/genome-sequence.minimal.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/data-serving/data-service/test/model/genome-sequence.test.ts b/data-serving/data-service/test/model/genome-sequence.test.ts new file mode 100644 index 000000000..7da2acf4e --- /dev/null +++ b/data-serving/data-service/test/model/genome-sequence.test.ts @@ -0,0 +1,42 @@ +import { + GenomeSequenceDocument, + genomeSequenceSchema, +} from '../../src/model/genome-sequence'; + +import { Error } from 'mongoose'; +import fullModel from './data/genome-sequence.full.json'; +import minimalModel from './data/genome-sequence.minimal.json'; +import mongoose from 'mongoose'; + +const GenomeSequence = mongoose.model( + 'GenomeSequence', + genomeSequenceSchema, +); + +describe('validate', () => { + it('genome sequence with non-conforming date is invalid', async () => { + return new GenomeSequence({ + ...minimalModel, + ...{ sampleCollectionDate: Date.parse('2019-10-31') }, + }).validate((e) => { + expect(e.name).toBe(Error.ValidationError.name); + }); + }); + + it('genome sequence with non-integer length is invalid', async () => { + return new GenomeSequence({ + ...minimalModel, + ...{ sequenceLength: 2.2 }, + }).validate((e) => { + expect(e.name).toBe(Error.ValidationError.name); + }); + }); + + it('minimal genome sequence model is valid', async () => { + return new GenomeSequence(minimalModel).validate(); + }); + + it('fully specified genome sequence model is valid', async () => { + return new GenomeSequence(fullModel).validate(); + }); +}); diff --git a/data-serving/samples/cases.json b/data-serving/samples/cases.json index f264ea1e3..ba1c4d92a 100644 --- a/data-serving/samples/cases.json +++ b/data-serving/samples/cases.json @@ -12,6 +12,18 @@ ], "ethnicity": "Other" }, + "genomeSequences": [ + { + "sampleCollectionDate": { + "$date": "2019-12-30T00:00:00Z" + }, + "repositoryUrl": "https://www.ncbi.nlm.nih.gov/nuccore/NC_045512", + "sequenceId": "NC_045512.2", + "sequenceName": "Severe acute respiratory syndrome coronavirus 2 isolate Wuhan-Hu-1, complete genome", + "sequenceLength": 33000, + "notes": "The reference sequence is identical to MN908947." + } + ], "location": { "country": "France", "administrativeAreaLevel1": "Île-de-France",