Queries and results
How Athena.js reads work across .select() chains, eager .findMany(...) calls, aliases, and typed result inference.
Athena.js exposes two read styles:
.select(...)for deferred column-string chains.findMany(...)for eager object-tree reads
Both start from .from(tableName). Use the string surface when a flat select is enough. Use findMany(...) when you want nested relations or clearer typed intent at the callsite.
.select(...) chains
const result = await athena.from("users").select("id, name, email").eq("active", true).limit(25);
if (result.error) {
console.error(result.error.message);
} else {
console.table(result.data);
}select() returns a SelectChain, not a promise. The request executes when you await the chain or terminate it with .single(...) / .maybeSingle(...).
Column lists
Omit the argument for all columns (*). Otherwise pass a comma-separated string or an array:
const { data } = await athena.from("users").select("id, name, email");
const { data: rows } = await athena.from("users").select(["id", "name"]);Column strings can rename response keys:
const { data } = await athena
.from("users")
.select("user_id:id, user_email:email, createdAt:created_at");See Select column aliases for the full alias rules.
.findMany(...) reads
findMany(...) is the canonical eager read surface for object-based selection trees:
const sections = await athena.from("orchestral_sections").findMany({
select: {
name: true,
instruments: {
select: {
name: true,
},
},
},
where: {
active: true,
},
orderBy: {
name: "asc",
},
limit: 10,
});Important behavior:
findMany(...)executes immediatelyselect,where,orderBy, andlimitare compiled into the existing gateway transport by default- typed relation inference is strongest on
fromModel(...) - the current Athena server contract expects the compiled transport, not top-level AST fetch bodies
See findMany AST and server contract for transport and compatibility details.
Single-row helpers
.single(...) and .maybeSingle(...) are read terminators that return one row or null.
const { data: user } = await athena
.from("users")
.select("id, name")
.eq("id", 42)
.single();
if (user) {
console.log(user.name);
}Combine them with sorting when you want the latest or oldest row.
Typing rows and relations
Annotate the row type for inference on data:
interface User {
id: number;
name: string;
email: string;
active: boolean;
}
const { data } = await athena.from<User>("users").select("id, name");
// data is User[] | nullWhen you use the typed registry, fromModel(...) can also infer relation output for findMany(...). On plain from<Row>(...) calls, unresolved relation leaves fall back to unknown.
Result shape
All awaitable reads resolve to AthenaResult<T>. The fields you usually care about are:
dataerrorstatusstatusTextcountraw
error is a structured object on failed results, so service code should read result.error.message instead of assuming a plain string.
Related
- Filtering — chain
.eq/.ilikebefore.select() - Pagination and limits —
.limit,.offset, page-based fields - Select column aliases
- findMany AST and server contract
- Overview