3.3. Attestations & Relations¶
3.3.1. The Attestation as Graph Node¶
In WHG v4, Attestations are nodes (vertices) in the graph, not records with embedded relationship fields. They serve as junction points that bundle together claims about a Thing with its attributes (Names, Geometries, Timespans) and provenance (Sources).
3.3.1.1. Attestation Node Structure¶
An Attestation node contains only metadata:
{
"_key": "att-001",
"_id": "attestations/att-001",
"sequence": null, // For ordered sequences in routes/itineraries
"connection_metadata": null, // For network relationships
"certainty": 0.95, // Confidence level (0.0-1.0)
"certainty_note": "Well-documented in primary sources",
"notes": "Additional context",
"created": "2024-01-15T10:30:00Z",
"modified": "2024-02-20T14:45:00Z",
"contributor": "researcher@example.edu"
}
Key Properties:
_key,_id: ArangoDB identifierssequence: Integer for ordering waypoints in routes/itinerariesconnection_metadata: JSON for network connection details (trade goods, flow direction, etc.)certainty: Confidence value (0.0-1.0)certainty_note: Explanation of certainty assessmentnotes: Free-text contextcreated,modified: Temporal metadatacontributor: User or system that created the attestation
What’s NOT in the Attestation:
No
subject_idorobject_idfieldsNo
relation_typefieldNo
sourcearray
These are all expressed through edges in the EDGE collection.
3.3.2. Relationships Through Edges¶
All relationships are expressed through the unified EDGE collection. Each edge has:
{
"_key": "edge-001",
"_id": "edges/edge-001",
"_from": "things/constantinople", // Source node
"_to": "attestations/att-001", // Target node
"edge_type": "subject_of", // Type of relationship
"role": "subject", // Optional disambiguation
"properties": {}, // Optional edge-specific data
"created": "2024-01-15T10:30:00Z"
}
3.3.2.1. Core Edge Types¶
Edge Type |
Direction |
Meaning |
|---|---|---|
|
Thing → Attestation |
This attestation is about this Thing |
|
Attestation → Name |
This attestation claims this Name |
|
Attestation → Geometry |
This attestation claims this Geometry |
|
Attestation → Timespan |
This attestation claims this Timespan |
|
Attestation → Authority |
This attestation is backed by this Source |
|
Attestation → Thing |
This attestation connects to another Thing |
|
Attestation → Authority |
This attestation uses this Relation Type |
|
Attestation → Attestation |
This attestation comments on another |
|
Authority → Authority |
This Source is part of this Dataset |
3.3.4. Complete Examples¶
3.3.4.1. Example 1: Thing with Name and Timespan¶
Scenario: “The city was called ‘Tenochtitlan’ during 1325-1521 CE”
Graph structure:
Thing(mexico-city) ←[subject_of]← Attestation(att-001)
↓ [attests_name]
Name(tenochtitlan)
↓ [attests_timespan]
Timespan(1325-1521)
↓ [sourced_by]
Authority(codex-mendoza)
Documents:
Thing:
{
"_id": "things/mexico-city",
"thing_type": "location",
"description": "Major city in modern Mexico"
}
Attestation:
{
"_id": "attestations/att-001",
"certainty": 0.95,
"notes": "Aztec period name"
}
Name:
{
"_id": "names/tenochtitlan",
"name": "Tenochtitlan",
"language": "nah",
"name_type": ["toponym"]
}
Timespan:
{
"_id": "timespans/aztec-tenochtitlan",
"start_earliest": "1325-01-01",
"start_latest": "1325-12-31",
"end_earliest": "1521-08-13",
"end_latest": "1521-08-13",
"precision": "year"
}
Authority (Source):
{
"_id": "authorities/codex-mendoza",
"authority_type": "source",
"citation": "Codex Mendoza, 16th century",
"uri": "https://example.org/codex-mendoza"
}
Edges:
// Thing to Attestation
{
"_from": "things/mexico-city",
"_to": "attestations/att-001",
"edge_type": "subject_of"
}
// Attestation to Name
{
"_from": "attestations/att-001",
"_to": "names/tenochtitlan",
"edge_type": "attests_name"
}
// Attestation to Timespan
{
"_from": "attestations/att-001",
"_to": "timespans/aztec-tenochtitlan",
"edge_type": "attests_timespan"
}
// Attestation to Source
{
"_from": "attestations/att-001",
"_to": "authorities/codex-mendoza",
"edge_type": "sourced_by"
}
Note on Timespan Fields: Internally, WHG uses stop_earliest and stop_latest for temporal bounds. When exporting to RDF/W3C Time format, these are mapped to end_earliest and end_latest for standards compliance. This example shows internal field names.
3.3.4.2. Example 2: Thing with Geometry and Different Timespan¶
Scenario: “The Tang Dynasty capital had these boundaries during 618-907 CE”
Graph structure:
Thing(changan) ←[subject_of]← Attestation(att-002)
↓ [attests_geometry]
Geometry(tang-walls)
↓ [attests_timespan]
Timespan(tang-dynasty)
↓ [sourced_by]
Authority(archaeological-survey)
Edges:
{
"_from": "things/changan",
"_to": "attestations/att-002",
"edge_type": "subject_of"
}
{
"_from": "attestations/att-002",
"_to": "geometries/tang-walls",
"edge_type": "attests_geometry"
}
{
"_from": "attestations/att-002",
"_to": "timespans/tang-dynasty",
"edge_type": "attests_timespan"
}
{
"_from": "attestations/att-002",
"_to": "authorities/archaeological-survey-2020",
"edge_type": "sourced_by"
}
3.3.4.3. Example 3: Thing-to-Thing Relationship¶
Scenario: “Alexandria was the capital of Ptolemaic Egypt”
Graph structure:
Thing(alexandria) ←[subject_of]← Attestation(att-003)
↓ [typed_by]
Authority(capital-of relation)
↓ [relates_to]
Thing(ptolemaic-egypt)
↓ [sourced_by]
Authority(source)
Edges:
// Thing to Attestation
{
"_from": "things/alexandria",
"_to": "attestations/att-003",
"edge_type": "subject_of"
}
// Attestation to Relation Type
{
"_from": "attestations/att-003",
"_to": "authorities/capital-of",
"edge_type": "typed_by"
}
// Attestation to Related Thing
{
"_from": "attestations/att-003",
"_to": "things/ptolemaic-egypt",
"edge_type": "relates_to"
}
// Attestation to Source
{
"_from": "attestations/att-003",
"_to": "authorities/historical-geography",
"edge_type": "sourced_by"
}
3.3.4.4. Example 4: Route Segment (Ordered Sequence)¶
Scenario: “Samarkand was the 15th waypoint on the Silk Road”
Graph structure:
Thing(samarkand) ←[subject_of]← Attestation(att-005)
↓ [typed_by]
Authority(member-of relation)
↓ [relates_to]
Thing(silk-road)
Attestation with sequence:
{
"_id": "attestations/att-005",
"sequence": 15,
"certainty": 0.9
}
Edges:
{
"_from": "things/samarkand",
"_to": "attestations/att-005",
"edge_type": "subject_of"
}
{
"_from": "attestations/att-005",
"_to": "authorities/member-of",
"edge_type": "typed_by"
}
{
"_from": "attestations/att-005",
"_to": "things/silk-road",
"edge_type": "relates_to"
}
{
"_from": "attestations/att-005",
"_to": "authorities/historical-atlas",
"edge_type": "sourced_by"
}
3.3.4.5. Example 5: Network Connection with Metadata¶
Scenario: “Constantinople had trade connections with Venice, exchanging spices and textiles”
Graph structure:
Thing(constantinople) ←[subject_of]← Attestation(att-007)
↓ [typed_by]
Authority(connected-to relation)
↓ [relates_to]
Thing(venice)
↓ [attests_timespan]
Timespan(byzantine-venetian)
Attestation with connection metadata:
{
"_id": "attestations/att-007",
"connection_metadata": {
"connection_type": "trade",
"directionality": "bidirectional",
"commodity": ["spices", "textiles", "metals"],
"intensity": 0.9
},
"certainty": 0.92
}
Edges:
{
"_from": "things/constantinople",
"_to": "attestations/att-007",
"edge_type": "subject_of"
}
{
"_from": "attestations/att-007",
"_to": "authorities/connected-to",
"edge_type": "typed_by"
}
{
"_from": "attestations/att-007",
"_to": "things/venice",
"edge_type": "relates_to"
}
{
"_from": "attestations/att-007",
"_to": "timespans/byzantine-venetian-trade",
"edge_type": "attests_timespan"
}
{
"_from": "attestations/att-007",
"_to": "authorities/trade-networks-db",
"edge_type": "sourced_by"
}
3.3.4.6. Example 6: Meta-Attestation¶
Scenario: “A modern scholarly article contradicts the Byzantine chronicle’s claim about Constantinople’s name”
Graph structure:
Attestation(att-001) ←[meta_attestation]← Attestation(att-meta)
↓ [sourced_by]
Authority(modern-article)
Meta-attestation:
{
"_id": "attestations/att-meta",
"certainty": 0.85,
"notes": "Recent archaeological evidence suggests different dating"
}
Edge:
{
"_from": "attestations/att-meta",
"_to": "attestations/att-001",
"edge_type": "meta_attestation",
"properties": {
"meta_type": "contradicts" // Could also be "supports", "supersedes", "bundles"
}
}
Note on Meta-Attestation Edge Type: The edge connecting meta-attestations uses edge_type: "meta_attestation" with an optional meta_type property in the edge’s properties field to specify the nature of the relationship (contradicts, supports, supersedes, etc.). This is distinct from the typed_by edge pattern used for Thing-to-Thing relationships.
3.3.5. Multiple Attestations for Same Thing¶
A single Thing can have multiple Attestations with different:
Names at different times
Geometries at different times
Conflicting claims from different sources
Example: Constantinople through time
Thing(constantinople) ←[subject_of]← Attestation(att-ancient)
↓ [attests_name]
Name(byzantion)
↓ [attests_timespan]
Timespan(667-BCE-330-CE)
Thing(constantinople) ←[subject_of]← Attestation(att-byzantine)
↓ [attests_name]
Name(konstantinoupolis)
↓ [attests_timespan]
Timespan(330-1453-CE)
Thing(constantinople) ←[subject_of]← Attestation(att-ottoman)
↓ [attests_name]
Name(istanbul)
↓ [attests_timespan]
Timespan(1453-present)
Each attestation is independent, with its own:
Name
Timespan
Source(s)
Certainty value
Notes
3.3.6. Querying Patterns¶
3.3.6.1. Find all names for a Thing at a specific time¶
// Find names for Constantinople in year 800 CE
FOR thing IN things
FILTER thing._id == "things/constantinople"
FOR att IN attestations
FOR e1 IN edges
FILTER e1._from == thing._id
FILTER e1._to == att._id
FILTER e1.edge_type == "subject_of"
// Get the name
FOR e2 IN edges
FILTER e2._from == att._id
FILTER e2.edge_type == "attests_name"
LET name = DOCUMENT(e2._to)
// Get the timespan
FOR e3 IN edges
FILTER e3._from == att._id
FILTER e3.edge_type == "attests_timespan"
LET timespan = DOCUMENT(e3._to)
// Check if 800 CE falls within the timespan
FILTER timespan.start_earliest <= "0800-01-01"
FILTER timespan.end_latest >= "0800-12-31"
RETURN {
name: name.name,
language: name.language,
timespan: timespan.label,
certainty: att.certainty
}
Note: This query uses end_latest in the filter. Remember that internally WHG stores this as stop_latest, so adjust field names based on your implementation context.
3.3.6.2. Find all Things connected via a specific relation type¶
// Find all capitals of empires
FOR att IN attestations
// Get the relation type
FOR e1 IN edges
FILTER e1._from == att._id
FILTER e1.edge_type == "typed_by"
LET relationType = DOCUMENT(e1._to)
FILTER relationType.label == "capital_of"
// Get subject Thing
FOR e2 IN edges
FILTER e2._to == att._id
FILTER e2.edge_type == "subject_of"
LET subject = DOCUMENT(e2._from)
// Get object Thing
FOR e3 IN edges
FILTER e3._from == att._id
FILTER e3.edge_type == "relates_to"
LET object = DOCUMENT(e3._to)
RETURN {
capital: subject.description,
empire: object.description,
certainty: att.certainty
}
3.3.7. Design Benefits¶
Flexibility: Each attestation is independent, allowing:
Multiple names/geometries per Thing across time
Conflicting claims to coexist
Rich provenance tracking
Reusability: Entities are shared:
Same Name can apply to multiple Things
Same Geometry can represent different Things at different times
Same Timespan can be referenced by many Attestations
Provenance: Every claim is traceable:
Source attribution via edges
Certainty values per attestation
Meta-attestations for scholarly discourse
Extensibility: New relation types can be added:
Through AUTHORITY documents
Without schema changes
With semantic validation (domain/range)
3.3.8. Migration from v3¶
The v3 attestation model embedded relationships within attestation records. The v4 model externalizes these into edges:
v3 Pattern:
{
"subject_id": "place-123",
"relation_type": "has_name",
"object_id": "name-456",
"source": ["source1"],
"timespan_id": "timespan-789"
}
v4 Pattern:
Attestation node (metadata only)
+ Edge to Thing (subject_of)
+ Edge to Name (attests_name)
+ Edge to Timespan (attests_timespan)
+ Edge to Authority (sourced_by)
This transformation enables true graph traversal and eliminates the need for complex JOIN operations.