Data Connect: All About Schemas

Many apps need to store persistent data, and most of the time, that data needs to be organized in a structured way. With Data Connect, you model your app data using schemas, and this blog post dives into what schemas are and how to use them.

We’ll use the movie review app example you might already know from the documentation and our previous deep-dive blog posts.

Declaring a Schema

Firebase Data Connect schemas are defined using GraphQL. The key components of GraphQL schema definitions are:

  • Type definition
  • Table name
  • @table directive, which includes the optional arguments of naming convention and key(s)

Here is an example from the movie tracker app:

type Movie @table(name: "Movies", singular: "movie", plural: "movies", key: ["id"])

This line has:

  • A type type definition, letting GraphQL know this is declaring a type (other examples of type definitions are query and mutation)
  • Movie as the name of the schema
  • A directive @table which signifies creation of a schema

Within the @table directive, there are a few optional fields:

  • name: defines the table name; by default, the table name is the schema name
  • singular: for implicit queries and mutations, this defines the name that gets used in the query / mutation that requires this table
  • plural: for implicit mutations, this defines the name that gets used in the mutation that requires this table
  • key: an optional list for the name of the table’s key(s)

By default, the singular naming convention will be the name of the table with a lower case first letter, and the plural one will be the singular with a “s” at the end. You only need to use singular or plural to adjust the name if it is different than the default.

Similarly, the key by default will be named id, and you do not need to declare this when you declare a schema.

Removing all of the defaults, the above declaration can be simplified to:

type Movie @table(name: "Movies")

Anatomy of a Schema

Now that you know how to declare a schema, how does a schema in its entirety look like? It is broken down into the following parts:

  • Declaration to create a schema, as described in the previous section
  • List of items in the schema

Here is an example schema for movies, written verbosely with all optional fields present except the schema declaration as covered above:

type Movie @table(name: "Movies") @index(fields: [releaseYear, rating], order: [ASC, DESC]) {
  id: UUID! @col(name: "movie_id") @default(expr: "uuidV4()")
  title: String! @col(name: "title")
  releaseYear: Int @col(name: "release_year") @index
  genre: String @col(name: "genre", dataType: "varchar(30)")
  rating: Int @col(name: "rating")
  description: String @col(name: "description")
}

Each line is the name of a column along with the data type of that column. Any data type followed by ! means this attribute is required. Data Connect supports a wide range of data types, some of which are in this code snippet like UUID, String, and Int. UUID is a special data type that indicates that this is a unique ID, which is useful for keys.

We also see @col, @default, and @index directives:

  • @col explicitly sets column information, including names and data type. The genre column is named “genre” with the String data type of at most 30 characters. By default, the first word of each line becomes the column name, so you only need @col(name: “...” if you want a different name.
  • @default lets you set default values. In the example above, an id defaults to a UUID generated by uuidV4().
  • @index defines a database index to optimize query performance. To create a single field SQL index, put @index on a @col field. You can specify order, but this doesn’t matter much for single field indexes as they can be scanned in both directions. To define a composite index, You can put @index(fields: [...]) on @table and define an order for each indexed column, defaulted to ASC. Above, releaseYear would be ordered in ascending order whereas rating would be ordered in descending order.

Removing all of the defaults, the above can be simplified to:

type Movie @table(name: "Movies") @index(fields: [releaseYear, rating], order: [ASC, DESC]) {
  id: UUID! @default(expr: "uuidV4()")
  title: String!
  releaseYear: Int @index
  genre: String @col(dataType: "varchar(30)")
  rating: Int
  description: String
}

Key Scalars

For databases optimized for speed, key scalars are an efficient way to identify objects. Data Connect automatically assembles these identifiers from key fields in your schemas, and the resulting scalars provide information about data identity and structure, accessible within a single cell. Key use cases include:

  • sequential operations: key scalars serve as unique identifiers for new records, simplifying subsequent operations
  • relational operations: key scalars provide access to relational keys, enabling more complex data manipulations

Server Values

Sometimes, your app might need server-computed values because the values need to be computed at the time of data creation. You can do this by using server values, where the server dynamically populates fields in your tables using stored or readily-computable values according to particular server-side expressions. For example, you can define a field with a timestamp applied when the field is accessed using the expression createdAt: Timestamp! @default(expr: "request.time"). This might be used when a user creates their account, so the schema could look like this:

type User @table(key: "uid") {
  // other fields
  createdAt: Date! @default(expr: "request.time")
}

Relationships Between Tables

A big part of using relational databases is (surprise!): relationships between tables, and Data Connect lets you do that. Here is an in-depth blog post on how to define one-to-one, one-to-many, and many-to-many relationships in your schemas.

Try it out!

Data modeling is a crucial part of any app that requires data, and hopefully this blog post clarifies how to define and use schemas in Data Connect. If you need more information about Data Connect, check out the documentation, and you can also check out other deep-dive articles. As it’s a new product, we’d love to hear your opinion and any feature requests you have as we’re hard at work improving and adding more features to the product. If you haven’t already, give Data Connect a try today - we can’t wait to see what you build with it!