Database Schema
This section describes the MongoDB collections, QuakeML alignment, and schema considerations used by the Earthquake Catalogue Platform.
QuakeML 1.2 Database Schema Design
Overview
This document outlines the expanded database schema to support all fields from the QuakeML 1.2 (Basic Event Description - BED) specification.
Design Principles
Frequently Queried Fields: Store as direct columns for performance
Complex Nested Data: Store as JSON for flexibility
Nullable Fields: Most fields are optional since not all catalogues provide all data
Backward Compatibility: Existing basic fields remain unchanged
QuakeML 1.2 Structure
Based on ObsPy implementation and QuakeML BED specification:
erDiagram
EVENT ||--o{ ORIGIN : "contains"
EVENT ||--o{ MAGNITUDE : "contains"
EVENT ||--o{ FOCAL_MECHANISM : "contains"
EVENT ||--o{ PICK : "contains"
EVENT ||--o{ AMPLITUDE : "contains"
ORIGIN ||--o{ ARRIVAL : "contains"
ORIGIN }|..|| EVENT : "preferred for"
MAGNITUDE }|--|| ORIGIN : "derived from"
MAGNITUDE }|..|| EVENT : "preferred for"
FOCAL_MECHANISM }|--|| ORIGIN : "triggered by"
FOCAL_MECHANISM }|..|| EVENT : "preferred for"
ARRIVAL }|--|| PICK : "based on"
EVENT {
string publicID
string type
datetime creationTime
}
ORIGIN {
datetime time
float latitude
float longitude
float depth
json quality
}
MAGNITUDE {
float mag
string type
string methodID
}
FOCAL_MECHANISM {
float strike
float dip
float rake
json momentTensor
}
Event (Top Level)
Note
Fields marked with REQUIRED are mandatory for event creation.
publicID(string) REQUIRED - Unique resource identifiertype(string) - Event type (earthquake, explosion, etc.)typeCertainty(string) - Certainty of event typedescription(array) - Event descriptions (name, region, etc.)comment(array) - Additional commentscreationInfo(object) - Author, agency, creation time
Origin (Location Information)
publicID(string)time(object) REQUIRED - Origin time with uncertainty -value(datetime) REQUIRED -uncertainty(float)latitude(object) REQUIRED - Latitude with uncertainty -value(float) REQUIRED -uncertainty(float)longitude(object) REQUIRED - Longitude with uncertainty -value(float) REQUIRED -uncertainty(float)depth(object) - Depth with uncertainty -value(float in meters) -uncertainty(float)depthType(string) - How depth was determinedtimeFixed(boolean) - Whether time was fixedepicenterFixed(boolean) - Whether epicenter was fixedquality(object) - Quality metrics -associatedPhaseCount(int) -usedPhaseCount(int) -associatedStationCount(int) -usedStationCount(int) -depthPhaseCount(int) -standardError(float) -azimuthalGap(float) -secondaryAzimuthalGap(float) -groundTruthLevel(string) -minimumDistance(float) -maximumDistance(float) -medianDistance(float)evaluationMode(string) - manual/automaticevaluationStatus(string) - preliminary/confirmed/reviewed/finaloriginUncertainty(object) - Uncertainty ellipse -horizontalUncertainty(float) -minHorizontalUncertainty(float) -maxHorizontalUncertainty(float) -azimuthMaxHorizontalUncertainty(float)creationInfo(object)
Magnitude
publicID(string)mag(object) REQUIRED - Magnitude value with uncertainty -value(float) REQUIRED -uncertainty(float)type(string) - ML, Mw, mb, Ms, etc.originID(string) - Reference to originmethodID(string) - Method usedstationCount(int) - Number of stations usedazimuthalGap(float)evaluationMode(string)evaluationStatus(string)creationInfo(object)
Pick (Phase Arrival Time)
publicID(string) REQUIREDtime(object) REQUIRED - Pick time with uncertainty -value(datetime) REQUIRED -uncertainty(float)waveformID(object) REQUIRED - Station/channel info -networkCode(string) REQUIRED -stationCode(string) REQUIRED -locationCode(string) -channelCode(string)filterID(string)methodID(string)phaseHint(string) - P, S, etc.polarity(string) - positive/negative/undecidableevaluationMode(string)evaluationStatus(string)creationInfo(object)
Arrival (Association of Pick with Origin)
publicID(string)pickID(string) REQUIRED - Reference to pickphase(string) REQUIRED - Phase identificationtimeCorrection(float)azimuth(float) - Azimuth from source to stationdistance(float) - Epicentral distance in degreestakeoffAngle(object) - Angle with uncertainty -value(float) -uncertainty(float)timeResidual(float) - Observed - calculated timehorizontalSlownessResidual(float)backazimuthResidual(float)timeWeight(float) - Weight in locationhorizontalSlownessWeight(float)backazimuthWeight(float)earthModelID(string)creationInfo(object)
FocalMechanism
publicID(string) REQUIREDtriggeringOriginID(string)nodalPlanes(object) - Two nodal planes -nodalPlane1(object)strike(object with value/uncertainty) REQUIREDdip(object with value/uncertainty) REQUIREDrake(object with value/uncertainty) REQUIRED
nodalPlane2(object) -strike(object with value/uncertainty) -dip(object with value/uncertainty) -rake(object with value/uncertainty)preferredPlane(int) - 1 or 2
principalAxes(object) - T, N, P axes -tAxis(object with azimuth/plunge/length) -pAxis(object with azimuth/plunge/length) -nAxis(object with azimuth/plunge/length)momentTensor(object) - Full moment tensor -derivedOriginID(string) -momentMagnitudeID(string) -scalarMoment(object with value/uncertainty) -tensor(object) - Mrr, Mtt, Mpp, Mrt, Mrp, Mtp -variance(float) -varianceReduction(float) -doubleCouple(float) -clvd(float) -iso(float) -sourceTimeFunction(object)evaluationMode(string)evaluationStatus(string)creationInfo(object)
Amplitude
publicID(string) REQUIREDgenericAmplitude(object) REQUIRED - Amplitude value with uncertainty -value(float) REQUIRED -uncertainty(float)type(string) - A, AML, etc.category(string) - point/mean/duration/period/integral/otherunit(string) - m, m/s, m/(s*s), etc.methodID(string)period(object) - Dominant period with uncertainty -value(float) -uncertainty(float)snr(float) - Signal-to-noise ratiotimeWindow(object) - Time window used -reference(datetime) -begin(float) -end(float)pickID(string) - Reference to pickwaveformID(object) - Station/channel infofilterID(string)scalingTime(object) - Time of maximum amplitudemagnitudeHint(string)evaluationMode(string)evaluationStatus(string)creationInfo(object)
StationMagnitude
publicID(string) REQUIREDoriginID(string) REQUIREDmag(object) REQUIRED - Magnitude value with uncertainty -value(float) REQUIRED -uncertainty(float)type(string)amplitudeID(string)methodID(string)waveformID(object)creationInfo(object)
Proposed Database Schema
Core Columns (Frequently Queried)
The following table shows the database schema with required fields marked:
Field |
Status |
Description |
|---|---|---|
|
REQUIRED |
Primary key identifier |
|
REQUIRED |
Reference to parent catalogue |
|
REQUIRED |
Event origin time (ISO 8601) |
|
REQUIRED |
Epicenter latitude (-90 to 90) |
|
REQUIRED |
Epicenter longitude (-180 to 180) |
|
REQUIRED |
Event magnitude value |
|
REQUIRED |
JSON array of source event references |
|
Optional |
Depth in kilometers |
|
Optional |
QuakeML public identifier |
|
Optional |
Event type (earthquake, explosion, etc.) |
CREATE TABLE merged_events (
-- Required fields (NOT NULL)
id TEXT PRIMARY KEY, -- REQUIRED
catalogue_id TEXT NOT NULL, -- REQUIRED
time DATETIME NOT NULL, -- REQUIRED
latitude REAL NOT NULL, -- REQUIRED
longitude REAL NOT NULL, -- REQUIRED
magnitude REAL NOT NULL, -- REQUIRED
source_events TEXT NOT NULL, -- REQUIRED
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
-- Optional event metadata
event_public_id TEXT,
event_type TEXT,
event_type_certainty TEXT,
depth REAL,
-- Optional origin uncertainties
time_uncertainty REAL,
latitude_uncertainty REAL,
longitude_uncertainty REAL,
depth_uncertainty REAL,
-- Optional magnitude details
magnitude_type TEXT,
magnitude_uncertainty REAL,
magnitude_station_count INTEGER,
-- Optional origin quality metrics
azimuthal_gap REAL,
used_phase_count INTEGER,
used_station_count INTEGER,
standard_error REAL,
-- Optional evaluation metadata
evaluation_mode TEXT,
evaluation_status TEXT,
-- Optional complex nested data as JSON
origin_quality JSON, -- Full OriginQuality object
origins JSON, -- Array of all origins
magnitudes JSON, -- Array of all magnitudes
picks JSON, -- Array of picks
arrivals JSON, -- Array of arrivals
focal_mechanisms JSON, -- Array of focal mechanisms
amplitudes JSON, -- Array of amplitudes
station_magnitudes JSON, -- Array of station magnitudes
event_descriptions JSON, -- Array of event descriptions
comments JSON, -- Array of comments
creation_info JSON, -- CreationInfo object
FOREIGN KEY (catalogue_id) REFERENCES merged_catalogues(id) ON DELETE CASCADE
);
Indexes for Performance
CREATE INDEX idx_event_type ON merged_events(event_type);
CREATE INDEX idx_magnitude_type ON merged_events(magnitude_type);
CREATE INDEX idx_evaluation_status ON merged_events(evaluation_status);
CREATE INDEX idx_azimuthal_gap ON merged_events(azimuthal_gap);
TypeScript Interfaces
See lib/types/quakeml.ts for comprehensive type definitions.
Migration Strategy
Add new columns with ALTER TABLE statements
Existing data remains valid (new columns are nullable)
New QuakeML imports populate all fields
Merge algorithm preserves detailed information
Benefits
Complete Data Preservation: All QuakeML 1.2 fields are stored
Query Performance: Common fields are indexed columns
Flexibility: JSON columns allow for complex nested structures
Backward Compatibility: Existing code continues to work
Research Value: Detailed seismological data available for analysis
flowchart LR
subgraph Client["🖥️ Client Browser"]
UI["React UI Components"]
State["React State Management"]
Maps["Leaflet Map Visualizations"]
end
subgraph NextJS["⚡ Next.js 13+ Application"]
subgraph Frontend["Frontend (App Router)"]
Pages["Pages & Layouts"]
Components["React Components"]
Hooks["Custom Hooks"]
end
subgraph Backend["Backend (API Routes)"]
UploadAPI["/api/upload"]
CataloguesAPI["/api/catalogues"]
EventsAPI["/api/events"]
MergeAPI["/api/merge"]
ImportAPI["/api/import"]
end
subgraph Libraries["Core Libraries"]
Parsers["lib/parsers.ts<br/>CSV, JSON, QuakeML"]
EqUtils["lib/earthquake-utils.ts<br/>Validation & Normalization"]
QualityCheck["lib/data-quality-checker.ts"]
CrossField["lib/cross-field-validation.ts"]
QuakeML["lib/quakeml-parser.ts"]
end
end
subgraph Database["💾 MongoDB Database"]
DB[(earthquake_catalogue)]
Collections[("Collections<br/>catalogues, events")]
Indexes[("Indexes")]
end
subgraph External["🌐 External Services"]
GeoNet["GeoNet API<br/>(NZ Earthquakes)"]
end
UI --> Pages
State --> Components
Maps --> Components
Pages --> Backend
Components --> Hooks
Backend --> Libraries
Libraries --> DB
DB --> Collections
Collections --> Indexes
ImportAPI --> External
classDef frontend fill:#3b82f6,stroke:#1d4ed8,color:#fff
classDef backend fill:#10b981,stroke:#059669,color:#fff
classDef db fill:#f59e0b,stroke:#d97706,color:#fff
classDef external fill:#8b5cf6,stroke:#7c3aed,color:#fff
class UI,State,Maps,Pages,Components,Hooks frontend
class UploadAPI,CataloguesAPI,EventsAPI,MergeAPI,ImportAPI backend
class DB,Collections,Indexes db
class GeoNet external