Customize primary keys
Customize primary keys
By default, DataStore models have an id field that is automatically populated on the client with a UUID v4, allowing DataStore to generate non-colliding globally unique identifiers in a scalable way. While UUIDs have desirable properties (they are large, non-sequential and opaque), there are times when a custom primary key, also known as custom identifier, is needed. For instance, to:
- Have friendly/readable identifiers (surrogate/opaque vs. natural keys)
 - Define composite primary keys
 - Customize data partitioning to optimize for scale (especially important when planning to handle large amounts of data in short periods of time)
 - Selectively synchronize data to clients (e.g. by fields like 
deviceId,userIdor similar) - Prioritize the sort order in which objects are returned by the sync queries
 - Make existing data consumable and syncable by DataStore
 
A schema with the typical id field looks like this:
type Book @model {  id: ID!  title: String!  description: String}You can customize the primary key by adding the @primaryKey directive to a field:
type Book @model {  isbn: ID! @primaryKey  title: String!  description: String}You can also require multiple fields to define your primary key. When your primary key references multiple fields, it's called a composite key. In the example below, the primary key is defined by the isbn and title fields:
type Book @model {  isbn: ID! @primaryKey(sortKeyFields: ["title"])  title: String!  description: String}Determine when the primary key field is auto-populated upon record creation
When you create a record with DataStore, a UUID is automatically populated for the default id: ID! primary key field. When working with custom primary keys, DataStore will automatically populate the key fields in the following conditions:
| Description | Type | Autopopulated with UUID | 
|---|---|---|
Without   |  | ✅ Yes | 
Without   |  | ✅ Yes | 
  |  | ❌ No | 
Explicit   |  | ✅ Yes | 
Explicit   |  | ✅ Yes | 
Explicit   |  | ✅ Yes | 
@primaryKey with no   |  | ❌ No | 
Querying records with custom primary keys
A record of a model with custom primary key can be queried with query predicate in the following ways:
final book = (  await Amplify.DataStore.query(    Book.classType,    where: Book.ISBN.eq('12345'),  ),)[0];You should always query by model identifier if the model has a composite primary key.
If you know the value of each field of the composite primary key, you can create a instance of the model identifier by using codegen generated class to create a query predicate:
final book = (  await Amplify.DataStore.query(    Book.classType,    where: Book.MODEL_IDENTIFIER.eq(      // BookModelIdentifier is a codegen generated class      // that is exported from ModelProvider.dart      BookModelIdentifier(        isbn: '12345',      ),    ),  ),)[0];If you have the reference of a model instance, you can use the getter modelIdentifier to get the identifier of this instance, and to create a query predicate with it.
final reQueriedBook = (  await Amplify.DataStore.query(    Book.classType,    where: Book.MODEL_IDENTIFIER.eq(      book.modelIdentifier,    ),  ),)[0];