|
| 1 | +# Entries Schema Documentation |
| 2 | + |
| 3 | +**Document Version:** 1.0 |
| 4 | +**Last Updated:** March 2026 |
| 5 | +**Status:** Active (2025 Standard) |
| 6 | +**Source:** Code analysis (`lib/server/entries.js`) |
| 7 | + |
| 8 | +--- |
| 9 | + |
| 10 | +## Overview |
| 11 | + |
| 12 | +The `entries` collection stores CGM (Continuous Glucose Monitor) sensor readings and related data. This includes SGV (sensor glucose values), MBG (meter blood glucose), and calibration data. |
| 13 | + |
| 14 | +**Collection Name:** `entries` |
| 15 | +**Primary Key:** `sysTime` + `type` (composite) |
| 16 | +**Primary Timestamp Field:** `sysTime` (ISO 8601, derived from `dateString` or `date`) |
| 17 | + |
| 18 | +--- |
| 19 | + |
| 20 | +## Core Fields |
| 21 | + |
| 22 | +| Field | Type | Required | Constraints | Description | |
| 23 | +|-------|------|----------|-------------|-------------| |
| 24 | +| `_id` | ObjectId | Yes (auto) | MongoDB ObjectId | Primary key, auto-generated by server | |
| 25 | +| `type` | String | Yes | `sgv`, `mbg`, `cal`, etc. | Type of entry | |
| 26 | +| `date` | Number | Yes | Epoch milliseconds | When the reading was taken | |
| 27 | +| `dateString` | String | Yes | ISO 8601 | Same as `date` in string format | |
| 28 | +| `sysTime` | String | Computed | ISO 8601 | Normalized timestamp (computed from `dateString` or `date`) | |
| 29 | +| `utcOffset` | Number | Computed | Minutes | UTC offset parsed from `dateString` | |
| 30 | + |
| 31 | +--- |
| 32 | + |
| 33 | +## SGV Fields (type: "sgv") |
| 34 | + |
| 35 | +| Field | Type | Constraints | Description | |
| 36 | +|-------|------|-------------|-------------| |
| 37 | +| `sgv` | Number | mg/dL or mmol/L | Sensor glucose value | |
| 38 | +| `direction` | String | Trend arrows | Glucose trend direction | |
| 39 | +| `noise` | Number | 0-4 | Signal noise level | |
| 40 | +| `filtered` | Number | Raw value | Filtered sensor signal | |
| 41 | +| `unfiltered` | Number | Raw value | Unfiltered sensor signal | |
| 42 | +| `rssi` | Number | dBm | Signal strength (Dexcom) | |
| 43 | + |
| 44 | +--- |
| 45 | + |
| 46 | +## Sync Identity Fields |
| 47 | + |
| 48 | +| Field | Type | Source | Description | |
| 49 | +|-------|------|--------|-------------| |
| 50 | +| `identifier` | String | Server-normalized | **Unified client sync identity** (see below) | |
| 51 | +| `device` | String | CGM app | Device/app identifier (e.g., `"xDrip-DexcomG6"`) | |
| 52 | + |
| 53 | +### Identifier Field Normalization (REQ-SYNC-072) |
| 54 | + |
| 55 | +As of v15.0.7, the server normalizes UUID values in `_id` into the `identifier` field when `UUID_HANDLING=true` (default): |
| 56 | + |
| 57 | +| Client | Sends | Server Action (UUID_HANDLING=true) | Server Action (UUID_HANDLING=false) | |
| 58 | +|--------|-------|-------------------------------------|--------------------------------------| |
| 59 | +| **Trio** | UUID in `_id` | Move to `identifier`, assign server ObjectId | Strip `_id`, assign ObjectId (UUID not preserved) | |
| 60 | +| **Loop** (entries) | ObjectId (from cache) | Normal ObjectId behavior | Normal ObjectId behavior | |
| 61 | + |
| 62 | +**Note**: The `UUID_HANDLING` env var controls **both** write-path normalization (identifier extraction) and read-path queries (GET/DELETE by UUID). |
| 63 | + |
| 64 | +**Important**: For entries, `sysTime + type` is ALWAYS the primary deduplication key. The `identifier` field is for client sync tracking only - it does NOT override the dedup logic. |
| 65 | + |
| 66 | +--- |
| 67 | + |
| 68 | +## Deduplication Behavior |
| 69 | + |
| 70 | +Entries use **sysTime + type** as the composite unique key: |
| 71 | + |
| 72 | +```javascript |
| 73 | +// Upsert query for entries (lib/server/entries.js) |
| 74 | +{ sysTime: doc.sysTime, type: doc.type } |
| 75 | +``` |
| 76 | + |
| 77 | +This means: |
| 78 | +- Two SGV readings at the same `sysTime` will be deduplicated (one overwrites the other) |
| 79 | +- Different entry types (SGV vs MBG) at the same time are allowed |
| 80 | +- Re-uploading the same reading updates the existing document |
| 81 | + |
| 82 | +### UUID _id Handling |
| 83 | + |
| 84 | +When a client sends a UUID as `_id`: |
| 85 | + |
| 86 | +1. **Extract**: UUID is copied to `identifier` field (when `UUID_HANDLING=true`) |
| 87 | +2. **Strip**: Non-ObjectId `_id` is removed before database operation |
| 88 | +3. **Upsert**: Server uses `sysTime + type` for matching |
| 89 | +4. **Assign**: Server-generated ObjectId becomes final `_id` |
| 90 | + |
| 91 | +This prevents the MongoDB "immutable field '_id'" error while preserving client sync identity (when enabled). |
| 92 | + |
| 93 | +--- |
| 94 | + |
| 95 | +## UUID_HANDLING Feature Flag |
| 96 | + |
| 97 | +The `UUID_HANDLING` environment variable controls both **write-path** normalization (identifier extraction) and **read-path** queries (GET/DELETE by UUID). |
| 98 | + |
| 99 | +When `UUID_HANDLING=true` (default): |
| 100 | + |
| 101 | +| Operation | Behavior | |
| 102 | +|-----------|----------| |
| 103 | +| POST/PUT with UUID `_id` | UUID moved to `identifier`, server assigns ObjectId | |
| 104 | +| GET by UUID | Searches by `identifier` field | |
| 105 | +| DELETE by UUID | Deletes by `identifier` field | |
| 106 | + |
| 107 | +When `UUID_HANDLING=false`: |
| 108 | + |
| 109 | +| Operation | Behavior | |
| 110 | +|-----------|----------| |
| 111 | +| POST/PUT with UUID `_id` | UUID `_id` stripped, ObjectId assigned (UUID not preserved) | |
| 112 | +| GET by UUID | Returns empty (no crash) | |
| 113 | +| DELETE by UUID | Deletes nothing (no crash) | |
| 114 | + |
| 115 | +**Note**: This only affects cases where a UUID is passed as the `_id` field (writes) or as the `_id` parameter in API calls (reads), e.g., `GET /api/v1/entries/{uuid}`. |
| 116 | + |
| 117 | +--- |
| 118 | + |
| 119 | +## Example Entry Document |
| 120 | + |
| 121 | +```json |
| 122 | +{ |
| 123 | + "_id": "507f1f77bcf86cd799439011", |
| 124 | + "type": "sgv", |
| 125 | + "sgv": 120, |
| 126 | + "direction": "Flat", |
| 127 | + "date": 1704067200000, |
| 128 | + "dateString": "2024-01-01T00:00:00.000Z", |
| 129 | + "sysTime": "2024-01-01T00:00:00.000Z", |
| 130 | + "utcOffset": 0, |
| 131 | + "identifier": "550e8400-e29b-41d4-a716-446655440000", |
| 132 | + "device": "xDrip-DexcomG6", |
| 133 | + "noise": 1 |
| 134 | +} |
| 135 | +``` |
| 136 | + |
| 137 | +--- |
| 138 | + |
| 139 | +## Related Documents |
| 140 | + |
| 141 | +- [Treatments Schema](treatments-schema.md) - Similar identifier normalization |
| 142 | +- [GAP-SYNC-045](../../../traceability/sync-identity-gaps.md#gap-sync-045) - Trio entries UUID issue |
| 143 | +- [REQ-SYNC-072](../../../traceability/sync-identity-requirements.md#req-sync-072) - Identifier normalization requirement |
0 commit comments