Can One Record Describe the Pump and Its Sensor?
Read a nested maintenance record field by field. Keep missing data separate from null, preserve measurement types, and decide which rules every document must follow.
13 sections · 4 questions · 1 coding challenge
The arrow keys move between sections too.
Keeping Object Structure in the Stored Record
BOTIE
For our maintenance screen, a sensor object keeps a reading beside its unit. The remaining question is whether every writer supplies the fields the reader expects. Flexible document shapes make a shared contract more useful, not less necessary.
Sources for this history
A Temperature Without Its Unit Is Not Much Use
Botie receives a value of 72 for P1. Is that a temperature? Which unit was used? When was it measured? Those questions belong to the same reading, so keeping their answers together helps us interpret it.
A document stores named fields, and a field can itself contain another document or an array. That gives us a way to keep related details together. It also gives us more ways to create a record that looks reasonable while leaving out something the reader needs.
The fixtures contain ordinary JSON-compatible values. Python dictionaries model their structure; no BSON driver or MongoDB server runs here.
Step 1 of 2
Each part answers a different question
This is one invented sensor document.
| Path | Value | Meaning |
|---|---|---|
| asset_id | P1 | Asset identity |
| sensor.latest | 72 | Measured number |
| sensor.unit | C | Unit attached to the number |
| sensor.observed_at | 2026-10-01T09:00:00Z | Observation time |
asset_id
- Value
- P1
- Meaning
- Asset identity
sensor.latest
- Value
- 72
- Meaning
- Measured number
sensor.unit
- Value
- C
- Meaning
- Unit attached to the number
sensor.observed_at
- Value
- 2026-10-01T09:00:00Z
- Meaning
- Observation time
Step 2 of 2
Three records require different interpretations
Assume null means the sensor reported no usable measurement.
| Sensor object | Field present? | Interpretation |
|---|---|---|
| {} | no | Writer supplied no latest field |
| {"latest":null} | yes | Explicitly no usable reading |
| {"latest":0} | yes | A measured zero |
{}
- Field present?
- no
- Interpretation
- Writer supplied no latest field
{"latest":null}
- Field present?
- yes
- Interpretation
- Explicitly no usable reading
{"latest":0}
- Field present?
- yes
- Interpretation
- A measured zero
Keep the measurement and its meaning together
The first tool enters the nested object; the second checks its leaf without losing missingness.
Does the sensor actually contain a latest field?
Read the sensor object, then probe the requested field without turning absence into an observed null.
BOTIE
Presence and stored value
{
"present": true,
"value": 0
}Follow the operations
1. Pump document
{ "asset_id": "P1", "sensor": { "latest": 0, "unit": "C" } }2. Read a document path
{ "latest": 0, "unit": "C" }3. Sensor field to inspect
latest
4. Check whether a field exists
{ "present": true, "value": 0 }5. Result
{ "present": true, "value": 0 }
The browser runs an explicit model of the mechanism. It does not connect to MongoDB or Redis, simulate their query planners, or establish their concurrency guarantees.
1. Start with the object the screen needs
A pump document might contain asset_id, site and a sensor object. Inside sensor, latest and unit describe one measurement. An array can hold a bounded collection such as the installed sensor channels.
Objects name fields; arrays preserve a sequence of values. If each array member is a reading, put the kind and value inside the same member. Two separate arrays need an additional ordering agreement to say which kind belongs to which value.
The structure should keep related facts together without hiding their identities.
2. Agree on types and units before reading values
The JSON number 72 and the JSON string "72" are different types. Converting arbitrary strings to numbers can hide invalid input. A number without a unit can also be misinterpreted even when its type is correct.
Define the writer contract: which fields are required, which numeric range is plausible, how timestamps are represented, and what a missing measurement means. Validate at the appropriate boundary. Database shape checks can support those rules; they cannot establish that a sensor measured the real world correctly.
A schema can confirm the presence of unit. Domain validation still needs to check which units are allowed.
3. Read the object one field at a time
Python dictionaries are useful for inspecting this mechanism. A dictionary lookup yields another dictionary at sensor; a second lookup yields latest. Brackets require the field to exist. A presence test allows us to describe an absent field explicitly.
JSON text is a representation sent between systems. json.loads parses it into Python values. MongoDB uses BSON internally, which has types beyond JSON’s basic set, including dates and ObjectIds. Do not assume a JSON round trip preserves every BSON type.
The worksheet uses JSON-compatible fixtures so its conversions are visible.
Parse a sensor record and follow its fields
The text contains JSON null; Python represents that value as None.
import json
record = json.loads('{"asset_id":"P1","sensor":{"latest":null,"unit":"C"}}')
sensor = record["sensor"]
print("latest" in sensor)
print(sensor["latest"])
print(sensor["unit"])True
None
CThe latest field exists and explicitly contains None. The unit remains a separate string.
4. Keep an omitted field separate from a reported null
Suppose an older writer never supplied latest. A newer writer supplies latest:null when the sensor fails. Both may become None if we call get without testing membership, losing useful evidence about what happened.
Our inspection result contains present and value. A missing field gives present false; a stored null gives present true with value None. For a longer path, an absent or non-object intermediate value means the requested leaf is unavailable. The full original document remains available if we need a richer validation explanation.
Zero is a value, null is an explicit marker, and omission means no field was supplied.
Check yourself
Questions on Parts 1 to 4
Question 1 of 2
Which presence result preserves the record?
Use the information below.
A sensor object is {"latest":null,"unit":"C"}. Null means an attempted measurement produced no usable result.5. Use a contract while the document shape evolves
Documents in a collection can have different fields, but the application still needs predictable meanings. A schema version can tell a reader which representation to interpret. A migration may update stored records; a compatibility reader may support both forms during a transition.
MongoDB supports schema validation, including a supported subset of JSON Schema expressed through $jsonSchema. Choose validation level and action deliberately. Requiring a field does not automatically fill it into old documents, and a validator definition alone is not a migration.
Test old and new writers together before retiring the older representation.
Run in your own environment
A validator for identity and a sensor object
This is a MongoDB validator expression, not a standalone insert command. It requires identity and a sensor object while allowing latest to be absent.
Pass this object as the validator option when creating or modifying a collection in a disposable MongoDB environment. The browser does not install validators.
{"$jsonSchema":{"bsonType":"object","required":["asset_id","sensor"],"properties":{"asset_id":{"bsonType":"string"},"sensor":{"bsonType":"object","required":["unit"],"properties":{"unit":{"enum":["C"]},"latest":{"bsonType":["double","int","long","null"]}}}}}}The deliberate optional latest field preserves the missing-versus-null cases. The validator does not prove that a measurement is accurate.
A validator for identity and a sensor object. Documentation checked .
6. Choose where the document should stop growing
A current sensor description is bounded. Every reading ever recorded is not. Embedding an ever-growing history makes each parent larger and complicates retrieval and updates. MongoDB also limits a BSON document to 16 MiB.
Choose a bounded embedded subset or store the history as separately identified records when growth demands it. The next lesson asks which facts belong inside the pump and which should remain references to independently maintained information.
A convenient screen shape is a starting point, not a reason to make every related fact part of one document.
Check yourself
Questions on Parts 1 to 6
Question 1 of 2
Which design question needs attention?
Use the information below.
A pump document embeds every reading forever; new readings arrive every second.Try it with Botie
Build with Botie
Write and run Python