Metadata and validation¶
User metadata¶
User metadata is a flat or nested JSON-compatible dictionary attached to each record. Any key–value pairs are accepted by default.
record = catalog.add_file(
path,
metadata={
"species": "CO2",
"year": 2024,
"tags": ["paris", "europe"],
},
)
Keys and values must be JSON-compatible. ogcat normalizes common Python values before validation, naming, and storage:
pathlib.Pathvalues become strings.datetime.dateanddatetime.datetimevalues become ISO 8601 strings.Mapping keys become strings and mapping values are normalized recursively.
Tuples and lists become JSON lists.
Sets and frozensets become deterministic lists where their normalized values can be sorted.
NumPy scalar-like values are converted through
.item()when available.
Unsupported objects are rejected with a TypeError naming the metadata path.
contains filters follow the type of the stored value:
strings use substring containment;
lists and other stored sequences use membership matching, and a list expected value requires every expected item to be present;
mappings match an expected mapping as a subset of key/value pairs;
scalar values fall back to equality.
matches = catalog.search(contains={"tags": "paris"})
all_tags = catalog.search(contains={"tags": ["paris", "europe"]})
site = catalog.search(contains={"site": {"code": "MHD"}})
For list-valued fields, membership is exact. This matters for suffixes:
# Does not match a stored suffix list such as [".zip"].
catalog.search(contains={"suffixes": "zip"})
# Does match, because ".zip" is the exact stored list member.
catalog.search(contains={"suffixes": ".zip"})
For file extensions and formats, prefer normalized metadata such as
format="zip" or derived_metadata.classification.format="zip" over fuzzy
suffix matching.
The equivalent CLI forms are:
ogcat search --catalog ./my-catalog tags:paris
ogcat search --catalog ./my-catalog --contains tags=paris
When list metadata is used in a naming template, list items are joined with
hyphens before path-safe normalisation, so ["a", "b", "c"] renders as
a-b-c.
Record schemas¶
A record schema declares which metadata fields a catalog expects. Schemas
are stored in catalog.json and are purely advisory unless you also enable
strict validation.
from ogcat import CatalogSpec, RecordSchema, MetadataFieldDescription
spec = CatalogSpec(
catalog_name="fluxes",
default_schema=RecordSchema(
display_fields=["id", "species", "year", "path"],
metadata_fields=[
MetadataFieldDescription(
name="species",
description="Chemical species code.",
example="CO2",
required=True,
),
MetadataFieldDescription(
name="year",
description="Calendar year.",
example=2024,
required=True,
),
],
),
)
display_fields declares the compact fields to show in search result previews
and notebook dataframes:
results = catalog.search(where={"species": "CO2"})
rows = results.rows()
df = results.to_dataframe(fields="default")
to_dataframe() requires pandas to be installed in the active environment.
Calling results.to_dataframe() with no fields still returns full record
dictionaries for compatibility.
Named schemas let one catalog hold different record types with different metadata expectations:
spec = CatalogSpec(
catalog_name="measurements",
record_schemas={
"surface": RecordSchema(
metadata_fields=[
MetadataFieldDescription(name="site", description="Site code.", required=True),
],
),
"satellite": RecordSchema(
metadata_fields=[
MetadataFieldDescription(name="platform", description="Satellite name.", required=True),
],
),
},
)
Validation¶
Validation checks that required fields declared by the effective schema are present in the record’s user metadata.
from ogcat import validate_metadata
report = validate_metadata(record.user_metadata, schema)
if report.issues:
for issue in report.issues:
print(issue.path, issue.message)
Validation is run automatically during add_file() and add_artifact().
Missing required fields are errors and block ingest. Use a
before_validate_metadata hook to fill defaults before validation, or call
validate_metadata() directly when you want to inspect a report without
writing a record.
The ogcat fields command¶
ogcat fields --catalog ./my-catalog
ogcat fields --catalog ./my-catalog --record-type surface
ogcat fields --catalog ./my-catalog --json
This prints the schema-declared metadata fields from the catalog spec.
To discover fields actually present in stored records, use:
ogcat fields --catalog ./my-catalog --stored
ogcat fields --catalog ./my-catalog --values species