Entity References
The EntityRef system for typed references between entities in properties and relationship metadata.
What is an EntityRef?
An EntityRef is a structured reference to another entity, used inside properties or relationship metadata. Any object with a pi field is treated as an EntityRef.
interface EntityRef {
pi: string; // Required - persistent identifier (entity ID)
type?: string; // Optional - type hint (e.g. "file", "user")
label?: string; // Optional - display hint (e.g. "My Document")
description?: string; // Optional - why this reference exists
}Field Details
| Field | Required | Description |
|---|---|---|
pi | Yes | The persistent identifier (entity ID) of the referenced entity. Must be a valid entity ID format. |
type | No | Type hint for the referenced entity (e.g., "file", "user", "collection"). Helps consumers understand the reference without fetching. |
label | No | Display label for the referenced entity. Avoids needing to fetch the entity just for display purposes. |
description | No | Human-readable description explaining why this reference exists or what it represents. |
Entity ID Formats
The pi field accepts the following entity ID formats:
| Format | Pattern | Example | Use Case |
|---|---|---|---|
| Standard ULID | 26 chars, Crockford Base32 | 01JUSER123ABC456789XYZ | Main network entities |
| Test network | II + 24 chars | IIUSER123ABC456789XYZA | Test network isolation |
| File entities | F + 25 chars | F0123456789ABCDEFGHIJKLMN | Deterministic file IDs |
| Chunk entities | C + 25 chars | C0123456789ABCDEFGHIJKLMN | Deterministic chunk IDs |
Usage in Entity Properties
EntityRefs let you embed references to other entities inside property values:
{
"properties": {
"author": {
"pi": "01JUSER123ABC456789XYZ",
"type": "user",
"label": "Alice Smith"
},
"source_document": {
"pi": "01JFILE456DEF789012ABC",
"type": "file",
"label": "Original Report.pdf",
"description": "The original document this analysis is based on"
}
}
}Usage in Relationship Properties
EntityRefs can also be used inside relationship metadata to attach references to specific relationships:
{
"relationships": [
{
"predicate": "member",
"peer": "01JUSER789GHI012345DEF",
"properties": {
"role": "editor",
"contract": {
"pi": "01JFILE456ABC789012XYZ",
"type": "file",
"label": "Editor Agreement",
"description": "Employment contract granting editor access"
}
}
}
]
}EntityRef vs Relationships
| Feature | EntityRef | Relationship |
|---|---|---|
| Where | Inside properties | Top-level relationships array |
| Traversal | Not indexed in graph | Indexed in Neo4j |
| Semantics | Metadata reference | Structural connection |
| Use case | "who authored this" | "this folder contains that file" |
Rule of thumb: Use relationships for structural connections that should be traversable. Use EntityRefs for metadata references that are informational.
Detection
The system automatically detects EntityRefs by looking for objects with a pi field. No special annotation is needed -- just include pi and it's treated as a reference.
The detection uses duck typing: any object with a pi string field is considered an EntityRef:
function isEntityRef(value: unknown): value is EntityRef {
return (
typeof value === 'object' &&
value !== null &&
'pi' in value &&
typeof value.pi === 'string'
);
}Inline References (in Text)
For references within text content (not property values that ARE references), use the arke: URI scheme instead of EntityRef:
{
"properties": {
"description": "See [Original Document](arke:01JFILE456ABC789012XYZ) for details."
}
}This is useful for:
- OCR text with derived images
- Rich text with entity links
- Document cross-references
The arke: scheme is domain-agnostic and future-proof since the entity ID is the stable identifier.
When to Use Each
| Approach | Use Case | Format |
|---|---|---|
| EntityRef | Property values that ARE references | { pi: "01J...", type: "file" } |
| Inline URI | References WITHIN text content | arke:01J... |
Utility Functions
The schema module exports several utilities for working with EntityRefs:
Creating References
import { ref } from '@arke/schema';
// Simple reference
const authorRef = ref('01JUSER123ABC456789XYZ');
// Reference with metadata
const docRef = ref('01JFILE456DEF789012ABC', {
type: 'file',
label: 'Original Report',
description: 'Source document for this analysis'
});Extracting References
import { extractEntityRefs, getReferencedPIs } from '@arke/schema';
// Get all refs with location info
const found = extractEntityRefs(entity);
// Returns: [{ ref: EntityRef, source: 'properties' | 'relationship', key: string, ... }]
// Get just the PI strings
const pis = getReferencedPIs(entity);
// Returns: ['01JUSER...', '01JFILE...']The extractEntityRefs function searches:
- Top-level values in
properties - Top-level values in each relationship's
properties