Query Patterns
Advanced querying with $hasDataType, $latest, and $not
Overview
LinkedRecords provides powerful query capabilities using special predicates and operators. This guide covers advanced querying techniques for filtering and finding records.
Basic Query Structure
Queries are expressed as objects where each key defines a named result set:
Query Predicates
$hasDataType
Filter by record type (KeyValueAttribute, LongTextAttribute, or BlobAttribute):
$latest(predicate)
Get the most recent value for a predicate. This is essential for state tracking:
$latest() is used when you track state changes over time by creating new facts
rather than deleting old ones. It returns records where the most recent fact
with that predicate matches the specified value.
$not(value)
Negation operator - find records where a predicate does NOT have a specific value:
Combining $latest and $not
The most common pattern is combining these for filtering by state:
Query by Record ID
Query specific records by their ID:
Compound Queries
Combine multiple criteria to narrow results:
This query finds:
- KeyValue records
- Classified as TodoList
- That are members of a specific collection
- Not archived (based on latest state)
- Where a specific organization is accountable
Relationship Queries
Find by Membership
Find by Custom Relationships
Find by Accountability
State Management Pattern
A common pattern is using separate state records to track item status.
Why Records Instead of Terms?
You might wonder: why create records for states instead of using terms directly
(e.g., [taskId, 'stateIs', 'Completed'])? The answer is permission control.
When states are records, you can use $canReferTo to control which users or
teams can set which states:
This enables granular workflows where different roles have different state transition permissions.
Implementation
Alternative: String-Based States
For simpler state tracking, you can use term values directly:
Note: "Completed" must be declared as a term
Multiple Result Sets
Fetch different categories in a single query:
Access Control in Queries
Queries automatically respect authorization - you only see records you have access to:
Loading Record Values
After querying, you can get record values:
Or use findAndLoadAll() for batch loading records:
Query Performance Tips
-
Be specific - Include type filters (
isA) to narrow results quickly -
Use accountability filters - Filter by
$isAccountableForto scope to specific organizations -
Combine criteria - Multiple criteria help the query engine optimize
-
Avoid fetching everything - Query for what you need rather than loading all records and filtering client-side
Best Practices
-
Use $latest for state tracking instead of deleting old state facts
-
Create dedicated state records for reusable state markers
-
Combine $latest and $not for filtering out unwanted states
-
Use meaningful predicate names that describe the relationship
-
Structure queries logically with the most selective criteria first