Once content has been saved in the CMS you'll want a way to retrieve it. Your CMS instance has methods to fetch specific Entries or search through all content.
import {cms} from '@/cms'
const homePage = await cms.get(HomePage())
A single Entry can be fetched using the get method.
import {Query} from 'alinea'
const query = Query(HomePage).whereId(homePageId)
const entry = await cms.get(query)
Multiple Entries can be fetched using the find method.
import {Query} from 'alinea'
const query = Query(BlogPost).whereParent(blogId)
const blogPosts = await cms.find(query)
A result set can be limited using skip and take.
// Skip the first 10 entries and return a maximum of 10
const query = Query(BlogPost).skip(10).take(10)
A result set can be ordered by passing one or multiple fields.
const ordered = Query(NewsItem).orderBy(NewsItem.publishDate.desc())
Results can be grouped by one or more fields.
const grouped = Query(NewsItem).groupBy(NewsItem.category)
Results can be filtered using the where function, or tailored functions such as whereId or whereLocale. To find Entries of any Type, use the Query functions directly.
// Any entry that matches your conditions
const searchAllEntries = Query.where(...)
If you're looking for Entries of a specific Type, pass it to the Query function to create a query of that Type. This will correctly infer the result TypeScript type.
// Only entries of type BlogPost will be found
const narrowByType = Query(BlogPost).where(...)
To search Entries by specific Fields use the where function. Fields can be compared to values using its conditional methods.
// If filtered by Type first it's possible to match fields
// on equality directly by passing an object. This does not
// work for any other comparison operator.
const withPath = Query(BlogPost).where({path: 'why-you-should-get-a-cat'})
// Comparisons can be made by using the conditional methods
// of the field you're comparing to.
const recent = Query(BlogPost).where(
BlogPost.publishedDate.isGreaterOrEqual(`2024-01-01`)
)
// Multiple conditions result in matching on both (AND).
const previousYear = Query(BlogPost).where(
BlogPost.publishedDate.isGreaterOrEqual(`2023-01-01`),
BlogPost.publishedDate.isLess(`2024-01-01`)
)
// To match any condition use Query.or (OR).
const isPetPost = Query(BlogPost).where(
Query.or(
BlogPost.tags.includes('cats'),
BlogPost.tags.includes('dogs')
)
)
Entries contain values managed by the CMS such as an id, parent, the assigned workspace, root or locale. Query has shortcuts to query these directly.
const german = Query.whereLocale('de')
const blogPosts = Query(BlogPost).whereParent(blog.id)
// Multiple conditions can be chained
const secretPages = Query(Secret).whereWorkspace('secret').whereRoot('pages')
Entries can be queried with search terms. Any (Rich) Text Field with the searchable option set to true is indexed.
// Search can be used in combination with conditions
const containsDogs = Query(BlogPost).where(...).search('dog')
// Multiple search terms can be used
const containsBothDogsAndCats = Query(BlogPost).search('cat', 'dog')
Resulting rows can be narrowed to contain only specific fields.
// Returns a select set of fields
const rows = Query(BlogPost).select({
// Entry fields are available on Query
id: Query.id,
url: Query.url,
title: BlogPost.title,
description: BlogPost.shortDescription
})
// You can include all available Entry fields at once
const rows = Query(BlogPost).select({
...Query.entry,
title: BlogPost.title,
description: BlogPost.shortDescription
})
Entries in Alinea are part of a content tree. This means they'll often have a parent Entry or contain children Entries. To query content from the parent(s) or children you can request it within the selection.
// Select a few fields from the parent Entries to render
// a breadcrumb navigation.
const breadcrumbs = Query.parents().select({
url: Query.url,
title: Query.title
})
// Use it directly in another select
const blogPosts = Query(BlogPost).select({
// Select the fields you want from this blog post
title: BlogPost.title,
body: BlogPost.body,
// ... and include the data of the parents
breadcrumbs
})
// You can use the spread operator to make the above more readable
const blogPosts = Query(BlogPost).select({
// Select all fields of the BlogPost type
...BlogPost,
breadcrumbs
})
// Similarly you can fetch parent and children in one query
const blog = Query(Blog).select({
title: Blog.title,
posts: Query.children(BlogPost)
})