Serverless Search

Benjamin Rabier
Benjamin Rabier
Marc Mettke
Marc Mettke
Jamie Barton
Jamie Barton
Serverless Search

Grafbase now supports Serverless Search!

Easily add search to your application without spending time on integrations or managing servers. You can index, query and filter through data that's stored within your Grafbase Database. It even supports fuzzy search, typos, and pagination!

Serverless Search is enabled using the @search directive on a database model or field:

type Order @model @search {
  customer: Email!
  total: Int! @default(value: 0)
  shipped: Boolean @default(value: false)
  notes: String
}

The @search directive will automatically index the data inside the Grafbase Database for that model (or field), and generate Serverless Search query.

It's that easy! Grafbase removes the need to make round trips away from the edge by bringing search results closer to your users.

If you don't already have a Grafbase backend, it's easy to get started:

npx grafbase init

Inside grafbase/schema.graphql replace the contents with a Order @model:

type Order @model {
  customer: Email!
  total: Int! @default(value: 0)
  shipped: Boolean @default(value: false)
  notes: String
}

Grafbase will automatically detect the directive @model and generate a GraphQL API for querying and mutating Order data — learn more.

Now add the @search directive to the same Order type to enable serverless search:

type Order @model @search {
  customer: Email!
  total: Int! @default(value: 0)
  shipped: Boolean @default(value: false)
  notes: String
}

That's it! Grafbase will automatically index your Order data.

If you'd prefer not to index everything but only certain fields you can do that as well:

type Order @model {
  customer: Email! @search
  total: Int! @default(value: 0) @search
  shipped: Boolean @default(value: false)
  notes: String @search
}

Finally run the Grafbase local development server:

npx grafbase dev

If you want to try the queries below you will need to add some Order entries to your database.


Example data
mutation {
  orderCreate(
    input: {
      customer: "hello@grafbase.com"
      total: 1000
      notes: "The best customer ever"
    }
  ) {
    order {
      id
    }
  }
}
mutation {
  orderCreate(input: { customer: "hello@graphql.org", total: 500 }) {
    order {
      id
    }
  }
}

Serverless Search can be used with the auto-generated orderSearch query.

You can query across all indexed String-like fields using the query argument.

query {
  orderSearch(first: 50, query: "hello") {
    edges {
      node {
        customer
        total
      }
    }
  }
}

Grafbase uses the levenshtein distance to tolerate typos of one character for words with a length or 4, or more. Typos of two characters are alloweed for words with a length of 8 or more.

query {
  orderSearch(first: 50, query: "hel1o") {
    edges {
      node {
        customer
        total
      }
    }
  }
}

By default, Grafbase searches across all fields but you can query to only search across precise String-like fields you set.

For example, let's only query against the field "notes":

query {
  orderSearch(first: 50, query: "hello", fields: ["notes"]) {
    edges {
      node {
        customer
        total
      }
    }
  }
}

The generated query for serverless search includes a filter argument that contains the input types for the indexed fields.

There are different types of operators depending on the field type used — learn more.

For example, let's filter Orders that have a total of 500 or less, and shipped is false:

query {
  orderSearch(
    first: 100
    filter: { total: { lte: 500 }, shipped: { eq: false } }
  ) {
    edges {
      node {
        customer
        total
      }
    }
  }
}

The search query also returns the field searchInfo that contains the totalHits of the query.

For example, let's reuse the query above and request for the totalHits in the same GraphQL request:

query {
  orderSearch(
    first: 100
    filter: { total: { lte: 500 }, shipped: { eq: false } }
  ) {
    searchInfo {
      totalHits
    }
    edges {
      node {
        customer
        total
      }
    }
  }
}

The generated query for Serverless Search works similarly to Database Pagination.

query {
  orderSearch(first: 10, after: "...") {
    edges {
      node {
        customer
        total
      }
    }
  }
}

You can dive deeper with Serverless Search by exploring the documentation.

We'd love to hear your feedback and ideas, so join us on Discord.