JSONPath Queries
JSONPath queries integrate directly with Loro documents so you can traverse complex data without writing ad hoc tree walkers. This guide outlines the query surface, highlights supported syntax, and walks through examples that you can adapt to your own application.
JSONPath functions such as
count(),length(),value(),match(), andsearch()are parsed but not evaluated at runtime. Each currently returnsJsonPathError::EvaluationError::Unimplemented.
Preparing Sample Data
The snippets below use the WASM bindings, but the same structure works with the
Rust API. We create a bookstore dataset inside a LoroDoc so we can run queries
against it.
⚠️ Illustration only: This approach stuffs plain JavaScript objects into a document for convenience. In production code prefer composing
LoroMapandLoroListinstances explicitly so you can control how data enters the CRDT and benefit from fine-grained updates.
import { } from "loro-crdt";
const = new ();
const = {
: [
{ : "1984", : "George Orwell", : 10, : true, : "978-0451524935" },
{ : "Animal Farm", : "George Orwell", : 8, : true },
{ : "Brave New World", : "Aldous Huxley", : 12, : false },
{ : "Fahrenheit 451", : "Ray Bradbury", : 9, : true, : "978-1451673318" },
{ : "The Great Gatsby", : "F. Scott Fitzgerald", : null, : true },
{ : "To Kill a Mockingbird", : "Harper Lee", : 11, : true },
{ : "The Catcher in the Rye", : "J.D. Salinger", : 10, : false },
{ : "Lord of the Flies", : "William Golding", : 9, : true },
{ : "Pride and Prejudice", : "Jane Austen", : 7, : true },
{ : "The Hobbit", : "J.R.R. Tolkien", : 14, : true }
],
: "George Orwell",
: 10,
: ["George Orwell", "Jane Austen"],
};
const = .("store");
.().(([, ]) => .(, ));
.();Executing JSONPath Queries
Run a query with the JSONPath method on WASM or jsonpath on Rust. The API
returns a list of values for any matches. Container results currently surface as
handlers internally, but that interface is still evolving and treated as
opaque in this guide.
const = new ();
// setup omitted for brevity
const = .("$.store.books[*].title");
.();
// => ["1984", "Animal Farm", ...]use loro::prelude::*;
let doc = LoroDoc::new();
// setup omitted for brevity
let titles = doc.jsonpath("$.store.books[*].title")?;
for title in titles {
if let ValueOrHandler::Value(value) = title {
println!("{value}");
}
}Supported Selectors and Filters
RFC 9535 syntax works end-to-end, including:
- Selectors – names, indices (positive/negative), slices, unions, wildcards,
and recursive descent (
..). - Filters – logical operators (
&&,||,!), comparisons, membership viain, substring checks withcontains, property existence, and nested subqueries through$(root) or@(current node). - Functions –
count(),length(), andvalue()are parsed, whilematch()andsearch()are reserved for expansion. All functions currently return an unimplemented evaluation error at runtime.
Cookbook Examples
Once the document is populated you can combine selectors and filters to extract precisely what you need.
| Query | Description | Result |
|---|---|---|
$.store.books[*].title | All book titles. | ["1984", "Animal Farm", "Brave New World", "Fahrenheit 451", "The Great Gatsby", "To Kill a Mockingbird", "The Catcher in the Rye", "Lord of the Flies", "Pride and Prejudice", "The Hobbit"] |
$.store.books[?(@.available)].title | Titles of books in stock. | ["1984", "Animal Farm", "The Great Gatsby", "To Kill a Mockingbird", "Lord of the Flies", "Pride and Prejudice", "The Hobbit"] |
$.store.books[?(@.author in $.store.featured_authors)].title | Books by featured authors. | ["1984", "Animal Farm", "Pride and Prejudice"] |
$.store.books[?(@.price > 12)].title | Books priced above 12. | ["The Hobbit"] |
$..price | All price fields via recursive descent. | [10, 8, 12, 9, null, 11, 10, 9, 7, 14] |
$.store.books[0:3].title | Slice syntax for the first three titles. | ["1984", "Animal Farm", "Brave New World"] |
$.store.books[0,2,-1].title | Union of specific indices. | ["1984", "Brave New World", "The Hobbit"] |
count($.store.books[?(@.available)]) | Planned helper to count available books (currently returns an unimplemented error). | JsonPathError::EvaluationError::Unimplemented |
length($.store.featured_authors) | Planned array length helper (currently returns an unimplemented error). | JsonPathError::EvaluationError::Unimplemented |
$.store.books[?(@.isbn && @.price >= $.store.min_price)].title | Filter by field existence and comparison. | ["1984"] |
$.store.books[?([email protected])].title | Negated availability filter. | ["Brave New World", "The Catcher in the Rye"] |
$.store.books[?(@.title contains "The")].author | Authors with “The” in the title. | ["F. Scott Fitzgerald", "J.R.R. Tolkien"] |
JSONPath always returns values in document order. When a filter references another query (such as
$.store.featured_authors), the subquery is evaluated for each candidate element.