⚠️ Links are currently not supported in Isar v4

Links

Os links permitem que você expresse relacionamentos entre objetos, como o autor de um comentário (Usuário). Você pode modelar relacionamentos 1:1, 1:n e n:n com links Isar. Usar links é menos ergonômico do que usar objetos incorporados e você deve usar objetos incorporados sempre que possível.

Pense no link como uma tabela separada que contém a relação. É semelhante às relações SQL, mas possui um conjunto de recursos e API diferentes.

IsarLink<T> pode conter nenhum ou um objeto relacionado e pode ser usado para expressar um relacionamento de um para um. IsarLink tem uma única propriedade chamada value que contém o objeto vinculado. Os links são preguiçosos, então você precisa dizer ao IsarLink para carregar ou salvar o valor explicitamente. Você pode fazer isso chamando linkProperty.load() e linkProperty.save().

Dica

A propriedade id das coleções de origem e destino de um link não deve ser final.

Para destinos não Web, os links são carregados automaticamente quando você os usa pela primeira vez. Vamos começar adicionando um IsarLink a uma coleção:

@collection
class Teacher {
  late int id;

  late String subject;
}

@collection
class Student {
  late int id;

  late String name;

  final teacher = IsarLink<Teacher>();
}

Definimos um vínculo entre teachers e students. Cada student pode ter exatamente um teacher neste exemplo.

Primeiro, criamos o teacher e o atribuímos a um student. Temos que fazer o .put() do teacher e salvar o link manualmente.

final mathTeacher = Teacher()..subject = 'Math';

final linda = Student()
  ..name = 'Linda'
  ..teacher.value = mathTeacher;

await isar.writeAsync((isar) async {
  await isar.students.put(linda);
  await isar.teachers.put(mathTeacher);
  await linda.teacher.save();
});

Agora podemos usar o link:

final linda = await isar.students.where().nameEqualTo('Linda').findFirst();

final teacher = linda.teacher.value; // > Teacher(subject: 'Math')

Vamos tentar a mesma coisa com código síncrono. Não precisamos salvar o link manualmente porque .putSync() salva automaticamente todos os links. Até cria o professor para nós.

final englishTeacher = Teacher()..subject = 'English';

final david = Student()
  ..name = 'David'
  ..teacher.value = englishTeacher;

isar.writeTxnSync(() {
  isar.students.putSync(david);
});

Faria mais sentido se o aluno do exemplo anterior pudesse ter vários professores. Felizmente, Isar tem IsarLinks<T>, que pode conter vários objetos relacionados e expressar um relacionamento para muitos.

IsarLinks<T> estende Set<T> e expõe todos os métodos permitidos para sets.

IsarLinks se comporta muito como IsarLink e também é preguiçoso. Para carregar todos os objetos vinculados, chame linkProperty.load(). Para persistir as alterações, chame linkProperty.save().

Internamente, IsarLink e IsarLinks são representados da mesma maneira. Podemos atualizar o IsarLink<Teacher> de antes para um IsarLinks<Teacher> para atribuir vários professores a um único aluno (sem perder dados).

@collection
class Student {
  late int id;

  late String name;

  final teachers = IsarLinks<Teacher>();
}

Isso funciona porque não mudamos o nome do link (professor), então Isar se lembra de antes.

final biologyTeacher = Teacher()..subject = 'Biology';

final linda = isar.students.where()
  .filter()
  .nameEqualTo('Linda')
  .findFirst();

print(linda.teachers); // {Teacher('Math')}

linda.teachers.add(biologyTeacher);

await isar.writeAsync((isar) async {
  await linda.teachers.save();
});

print(linda.teachers); // {Teacher('Math'), Teacher('Biology')}

Eu ouço você perguntar: "E se quisermos expressar relacionamentos reversos?". Não se preocupe; agora vamos apresentar backlinks.

Backlinks são links na direção inversa. Cada link sempre tem um backlink implícito. Você pode disponibilizá-lo para seu aplicativo anotando um IsarLink ou IsarLinks com @Backlink().

Backlinks não requerem memória ou recursos adicionais; você pode adicionar, remover e renomeá-los livremente sem perder dados.

Queremos saber quais students um teacher específico tem, então definimos um backlink:

@collection
class Teacher {
  Id id;

  late String subject;

  @Backlink(to: 'teacher')
  final student = IsarLinks<Student>();
}

Precisamos especificar o link para o qual o backlink aponta. É possível ter vários links diferentes entre dois objetos.

IsarLink e IsarLinks possuem um construtor sem argumentos, que deve ser usado para atribuir a propriedade link quando o objeto for criado. É uma boa prática tornar as propriedades do link final.

Quando você faz o put() do seu objeto pela primeira vez, o link é inicializado com a coleção de origem e destino, e você pode chamar métodos como load() e save(). Um link começa a rastrear as alterações imediatamente após sua criação, para que você possa adicionar e remover relações antes mesmo de o link ser inicializado.

Perigo

É ilegal mover um link para outro objeto.