Querying content

    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.

    Content can be queried within React server components (and functions that run on the server such as generateStaticParams).

    import {cms} from '@/cms'
    import {Query} from 'alinea'
    
    export default async function HomePage() {
      const homePage = await cms.get({type: HomePage})
      return <h1>{homePage.title}</h1>
    }

    Getting a specific Entry

    A single Entry can be fetched using the get method.

    const entry = await cms.get({
      type: HomePage,
      id: homePageId
    })

    Querying multiple Entries

    Multiple Entries can be fetched using the find method.

    const blogPosts = await cms.find({
      type: BlogPost,
      parentId: blogId
    })

    Limiting results

    A result set can be limited using skip and take.

    // Skip the first 10 entries and return a maximum of 10
    const posts = await cms.find({
      type: BlogPost,
      skip: 10,
      take: 10
    })

    Order results

    A result set can be ordered by passing one or multiple fields.

    const ordered = await cms.find({
      type: NewsItem,
      orderBy: {desc: NewsItem.publishDate}
    })

    Group by

    Results can be grouped by one or more fields.

    const grouped = await cms.find({
      type: NewsItem,
      orderBy: NewsItem.category
    })

    Filtering by Field values

    To search Entries by specific Fields use the filter option.

    // 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 = await cms.get({
      type: BlogPost,
      filter: {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 = await cms.find({
      type: BlogPost,
      filter: {publishedDate: {gte: `2024-01-01`}}
    })
    
    // Multiple conditions result in matching on both (AND).
    const postsOf2023 = await cms.find({
      type: BlogPost,
      filter: {
        publishedDate: {
          lt: '2024-01-01',
          gte: '2023-01-01'
        }
      }
    })

    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 = await cms.find({
      type: BlogPost,
      search: 'dog'
    })
    
    // Multiple search terms can be used
    const containsBothDogsAndCats = await cms.find({
      type: BlogPost,
      search: ['dog', 'cat']
    })

    Selecting Fields

    Resulting rows can be narrowed to contain only specific fields.

    import {Query} from 'alinea'
    
    // Returns a select set of fields 
    const rows = await cms.find({
      type: BlogPost,
      select: {
        // Entry fields are available on Query
        id: Query.id,
        url: Query.url,
        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.

    import {Query} from 'alinea'
    
    // 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 = await cms.find({
      type: 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 = await cms.find({
      type: BlogPost,
      select: {
        ...BlogPost,
        breadcrumbs
      }
    })
    
    // Similarly you can fetch parent and children in one query
    const blog = await cms.get({
      type: Blog,
      select: {
        ...Blog,
        posts: Query.children({type: blogPost})
      }
    })