Isar Plus

Schema

Define your data models with Isar collections

Schema

When you use Isar to store your app's data, you're dealing with collections. A collection is like a database table and can only contain a single type of Dart object.

Anatomy of a Collection

You define each Isar collection by annotating a class with @collection or @Collection().

@collection
class User {
  Id? id;

  String? firstName;

  String? lastName;
}

To persist a field, Isar must have access to it. Make it public or provide getter and setter methods.

Data Types

Isar supports the following data types:

Primitive Types

@collection
class PrimitiveTypes {
  PrimitiveTypes(this.id);

  final int id;

  bool? boolValue;
  int? intValue;
  double? doubleValue;
  DateTime? dateValue;
  String? stringValue;
}

Lists

@collection
class ListTypes {
  ListTypes(this.id);

  final int id;

  List<bool>? boolList;
  List<int>? intList;
  List<double>? doubleList;
  List<DateTime>? dateList;
  List<String>? stringList;
}

Lists cannot contain null values. Use nullable types instead.

Enums

Isar Plus supports Dart enums with two storage strategies:

By default, enums are stored by their index (ordinal). Simply use the enum directly without any annotation:

enum Status { active, inactive, pending }

@collection
class Task {
  Task(this.id);

  final int id;

  Status? status; // Stored as 0, 1, or 2
}

The stored values are:

  • Status.active0
  • Status.inactive1
  • Status.pending2

If you reorder enum values, existing stored data will map to different enum values. Add new values at the end or use custom values for stability.

For more control, define a field in your enum and annotate it with @enumValue. This field's value will be used for storage:

enum Status {
  active(1),
  inactive(2),
  pending(3);

  const Status(this.code);

  @enumValue
  final int code;
}

@collection
class Task {
  Task(this.id);

  final int id;

  Status? status; // Stored as 1, 2, or 3
}

Supported types for @enumValue:

  • byte - stored as single byte
  • short - stored as 16-bit integer
  • int - stored as 32-bit integer
  • String - stored as text
// String-based enum example
enum Priority {
  low('LOW'),
  medium('MEDIUM'),
  high('HIGH');

  const Priority(this.name);

  @enumValue
  final String name;
}

Migration from Isar v3

The @enumerated and @Enumerated(EnumType.ordinal/name) annotations from Isar v3 are no longer available. Use plain enums for ordinal storage or @enumValue for custom values.

Embedded Objects

@embedded
class Address {
  String? street;
  String? city;
  String? country;
}

@collection
class Person {
  Person(this.id);

  final int id;

  String? name;

  Address? address;

  List<Address>? addresses;
}

Ids

Every collection needs an Id field to uniquely identify objects.

@collection
class User {
  User(this.id);

  final int id;

  String? name;
}

For auto-incrementing IDs, use the collection.autoIncrement() method when inserting:

isar.write((isar) {
  final user = User(isar.users.autoIncrement());
  isar.users.put(user);
});

Custom IDs

@collection
class User {
  User(this.id);

  final int id; // You manage the ID

  String? name;
}

Field Annotations

@Index

Create indexes for better query performance:

@collection
class User {
  User(this.id);

  final int id;

  @Index()
  String? email;

  @Index(type: IndexType.value)
  String? username;

  @Index(caseSensitive: false)
  String? name;
}

@Ignore

Exclude fields from storage:

@collection
class User {
  User(this.id);

  final int id;

  String? name;

  @ignore
  String? temporaryData; // Not stored
}

@Name

Rename fields in the database:

@collection
class User {
  User(this.id);

  final int id;

  @Name("user_name")
  String? name;
}

@Size

Limit string size:

@collection
class User {
  User(this.id);

  final int id;

  @Size(max: 100)
  String? shortText;

  @Size(max: 1000)
  String? longText;
}

Composite Indexes

Create indexes on multiple fields:

@collection
@Index(composite: ['lastName', 'age'])
class User {
  User(this.id);

  final int id;

  String? firstName;

  String? lastName;

  int? age;
}

Modeling Relationships

Isar Plus v4 models relationships with embedded objects or manual ID fields instead of runtime link types. See the dedicated Relationships page for concrete examples lifted from the codebase.

Migration

Isar handles schema migrations automatically in most cases:

  • Adding new fields
  • Removing fields
  • Changing field types (with data loss)
  • Adding/removing indexes

Changing the type of an existing field will result in data loss for that field.

Next Steps

Last Update