Definir um modelo de objeto de domínio - SDK Node.js
Nesta página
- Definir um tipo de objeto de domínio
- Definir tipos de objetos de domínio com classes JavaScript
- Tipos de propriedade suportados
- Defina propriedades do objeto
- Especificar uma propriedade opcional
- Especificar uma chave primária
- Indexe uma propriedade
- Definir um índices the busca de texto completa
- Definir um valor de propriedade padrão
- Mapear uma propriedade ou classe para um nome diferente
- Definir Propriedades de Relacionamento
- Definir uma propriedade de relacionamento um-para-um
- Definir uma propriedade de relacionamento um-para-muitos
- Definir uma propriedade de relacionamento inversa
- Definir uma propriedade de objeto embarcado
- Definir um objeto assimétrico
- Definir dados não estruturados
Definir um tipo de objeto de domínio
Para definir um Tipo de objeto de Realm, crie um objeto de esquema que especifique o name
e properties
do tipo. O nome do tipo deve ser exclusivo entre os tipos de objeto em um Realm. Para obter detalhes sobre como definir propriedades específicas, consulte Definir propriedades de objeto.
Você pode definir seus esquemas com classes JavaScript (como a maioria dos exemplos nesta página), mas você também pode defini-los como objetos JavaScript.
const Car = { name: "Car", properties: { _id: "objectId", make: "string", model: "string", miles: "int?", }, };
Definir tipos de objetos de domínio com classes JavaScript
Você pode definir tipos de objetos de Realm com classes JavaScript. Para utilizar uma classe como um tipo de objeto, defina o esquema de objeto na propriedade estática schema
.
class Car extends Realm.Object { static schema = { name: "Car", properties: { _id: { type: "objectId", default: () => new Realm.BSON.ObjectId() }, make: "string", model: "string", miles: "int?", }, primaryKey: "_id", }; }
Observação
Os nomes das classes têm um limite máximo de 57 caracteres UTF-8.
Passe a própria classe para a propriedade schema do objeto Realm.Configuration ao abrir um domínio. Você pode então ler e gravar dados normalmente.
const realm = await Realm.open({ path: "myrealm", schema: [Car], }); let car1; realm.write(() => { car1 = realm.create(Car, { make: "Nissan", model: "Sentra", miles: 1000, }); });
Tipos de propriedade suportados
Cada propriedade em um objeto Realm tem um tipo de dados fortemente definido. O tipo de propriedade pode ser um tipo de dados primitivo ou um tipo de objeto definido no mesmo domínio. O tipo também especifica se a propriedade contém um único valor ou uma lista de valores.
O Realm suporta os seguintes tipos de dados primitivos:
bool
para valores booleanosint
edouble
, que mapeiam para valores JavaScriptnumber
Decimal128
para números de alta precisãostring
date
, que mapeia para a Datadata
, que mapeia para ArrayBufferobjectId
, que mapeia para ObjectId
Para especificar que um campo contém uma lista de um tipo de valor primitivo, acrescente []
ao nome do tipo.
Defina propriedades do objeto
Para definir uma propriedade para um tipo de objeto, crie um par chave-valor que represente o nome e o tipo de dados da propriedade no campo properties
.
O seguinte esquema define um tipo de Car
que tem estas propriedades: _id
make
, model
e miles
.
class Car extends Realm.Object { static schema = { name: "Car", properties: { _id: { type: "objectId", default: () => new Realm.BSON.ObjectId() }, make: "string", model: "string", miles: "int?", }, primaryKey: "_id", }; }
Especificar uma propriedade opcional
Para marcar uma propriedade como opcional, anexe um ponto de interrogação ?
ao seu tipo.
O seguinte esquema Car
define uma propriedade miles
opcional do tipo int
.
class Car extends Realm.Object { static schema = { name: "Car", properties: { _id: { type: "objectId", default: () => new Realm.BSON.ObjectId() }, make: "string", model: "string", miles: "int?", }, primaryKey: "_id", }; }
Especificar uma chave primária
Para especificar uma propriedade como uma chave primária do tipo de objeto, configure o campo primaryKey
do esquema para o nome da propriedade.
Observação
Uma chave primária é uma propriedade que identifica exclusivamente um objeto. O Realm indexa automaticamente as propriedades de chave primária, o que lhe permite ler e modificar objetos com eficiência com base em sua chave primária.
Se um tipo de objeto tiver uma chave primária, todos os objetos desse tipo deverão incluir a propriedade da chave primária com um valor exclusivo entre objetos do mesmo tipo em um domínio. Um tipo de objeto pode ter no máximo uma chave primária. Não é possível alterar a propriedade de chave primária de um tipo de objeto após qualquer objeto desse tipo ser adicionado a um domínio, e não é possível modificar o valor da chave primária de um objeto.
O seguinte esquema de objeto do Car
especifica a propriedade _id
como sua chave primária.
class Car extends Realm.Object { static schema = { name: "Car", properties: { _id: { type: "objectId", default: () => new Realm.BSON.ObjectId() }, make: "string", model: "string", miles: "int?", }, primaryKey: "_id", }; }
Indexe uma propriedade
O Realm permite a indexação para propriedades de string, inteiros, booleanos, Date
, UUID
e ObjectId
. Para definir um índice para uma determinada propriedade, defina indexed
para true
.
Observação
Um índice aumenta significativamente a velocidade de certas operações de leitura ao custo de tempos de gravação um pouco mais lentos e sobrecarga adicional de armazenamento e memória. O Realm armazena índices no disco, o que torna seus arquivos de domínio maiores. Toda entrada do índice tem um mínimo de 12 bytes. A ordenação das entradas do índice suporta correspondências de igualdade eficientes e operações de query baseadas em intervalo.
É melhor adicionar índices somente ao otimizar o desempenho de leitura para situações específicas.
O seguinte esquema de objeto do Car
define um índice na propriedade _id
.
class Car extends Realm.Object { static schema = { name: "Car", properties: { _id: { type: "objectId", indexed: true }, make: "string", model_name: { type: "string", mapTo: "modelName" }, miles: { type: "int", default: 0 }, }, primaryKey: "_id", }; }
Definir um índices the busca de texto completa
Além dos índices padrão, o Realm também suporta índices de Pesquisa de Texto Completo (FTS) em propriedades de string. Embora você possa query um campo de string com ou sem um índice padrão, um índice FTS permite pesquisar várias palavras e frases e excluir outras.
Para obter mais informações sobre como fazer queries em índices FTS, consulte Filtrar com Full Text Search.
Para criar um índice FTS, configure o tipo indexado para 'full-text'
. Isso permite queries de texto completo na propriedade. No exemplo a seguir, definimos o tipo indexado para a propriedade name
como 'full-text'
:
class Book extends Realm.Object<Book> { name!: string; price?: number; static schema: ObjectSchema = { name: "Book", properties: { name: { type: "string", indexed: "full-text" }, price: "int?", }, }; }
Definir um valor de propriedade padrão
Para definir um valor padrão, configure o valor da propriedade para um objeto com um campo type
e um campo default
.
O seguinte esquema de objeto Car
especifica um valor padrão de 0
para a propriedade miles
:
class Car extends Realm.Object { static schema = { name: "Car", properties: { _id: { type: "objectId", indexed: true }, make: "string", model_name: { type: "string", mapTo: "modelName" }, miles: { type: "int", default: 0 }, }, primaryKey: "_id", }; }
Mapear uma propriedade ou classe para um nome diferente
Por padrão, o Realm utiliza o nome definido na classe de modelo para representar classes e campos internamente. Em alguns casos, você pode querer alterar esse comportamento. Por exemplo:
Para facilitar o trabalho em plataformas onde as convenções de nomenclatura são diferentes. Por exemplo, se os nomes das propriedades do esquema Device Sync usarem snake case, enquanto seu projeto usa camel case.
Para alterar um nome de campo ou classe sem forçar uma migração.
Para oferecer suporte a várias classes de modelo com o mesmo nome em pacotes diferentes.
Para usar um nome de classe maior que o limite de 57 caracteres imposto pelo Realm.
Você pode mapear uma classe ou nome de propriedade em seu código para um nome diferente para armazenar em um domínio. Se você gravar em um domínio sincronizado, o esquema Sync verá os valores armazenados usando a classe persistente ou o nome da propriedade.
Observe que as migrações devem usar o nome de classe ou propriedade persistente, e quaisquer erros de esquema relatados também usam o nome persistente.
Para usar em seu código um nome de classe diferente do que é armazenado em um domínio:
Defina a propriedade
name
do esquema do objeto de Realm como o nome que você deseja usar para armazenar o objeto.Use o nome da classe na propriedade
schema
da configuração do Realm quando você abrir o domínio.Use o nome mapeado para executar operações CRUD ou ao definir Inscrições flexible Sync.
No exemplo seguinte, o Realm armazena objetos criados com a classe Task
como Todo_Item
.
class Task extends Realm.Object { static schema = { // Set the schema's `name` property to the name you want to store. // Here, we store items as `Todo_Item` instead of the class's `Task` name. name: "Todo_Item", properties: { _id: "int", name: "string", owner_id: "string?", }, primaryKey: "_id", }; } const config = { // Use the class name in the Configuration's `schema` property when // opening the realm. schema: [Task], sync: { user: anonymousUser, flexible: true, initialSubscriptions: { update: (subs, realm) => { subs.add( realm // Use the mapped name in Flexible Sync subscriptions. .objects(`Todo_Item`) .filtered(`owner_id == "${anonymousUser.id}"`) ); }, }, }, }; const realm = await Realm.open(config); realm.write(() => { // Use the mapped name when performing CRUD operations. realm.create(`Todo_Item`, { _id: 12342245, owner_id: anonymousUser.id, name: "Test the Todo_Item object name", }); }); // Use the mapped name when performing CRUD operations. const assignedTasks = realm.objects(`Todo_Item`);
class Task extends Realm.Object<Task> { _id!: number; name!: string; owner_id?: string; static schema: ObjectSchema = { // Set the schema's `name` property to the name you want to store. // Here, we store items as `Todo_Item` instead of the class's `Task` name. name: "Todo_Item", properties: { _id: "int", name: "string", owner_id: "string?", }, primaryKey: "_id", }; } const config: Realm.Configuration = { // Use the class name in the Configuration's `schema` property when // opening the realm. schema: [Task], sync: { user: anonymousUser, flexible: true, initialSubscriptions: { update: (subs, realm) => { subs.add( realm // Use the mapped name in Flexible Sync subscriptions. .objects(`Todo_Item`) .filtered(`owner_id == "${anonymousUser.id}"`) ); }, }, }, }; const realm = await Realm.open(config); realm.write(() => { // Use the mapped name when performing CRUD operations. realm.create(`Todo_Item`, { _id: 12342245, owner_id: anonymousUser.id, name: "Test the Todo_Item object name", }); }); // Use the mapped name when performing CRUD operations. const assignedTasks = realm.objects(`Todo_Item`);
Para usar um nome de propriedade em seu código, diferente do armazenado em um Realm, coloque em mapTo
o nome da propriedade conforme aparece em seu código.
No seguinte esquema de objetos Car
, o Realm armazena o nome do modelo do carro com a propriedade snake case model_name
. O esquema mapeia a propriedade para modelName
para objetos utilizados no código do cliente .
class Car extends Realm.Object { static schema = { name: "Car", properties: { _id: { type: "objectId", indexed: true }, make: "string", model_name: { type: "string", mapTo: "modelName" }, miles: { type: "int", default: 0 }, }, primaryKey: "_id", }; }
Definir Propriedades de Relacionamento
Definir uma propriedade de relacionamento um-para-um
Um relacionamento para-um mapeia uma propriedade para uma instância única de outro tipo de objeto. Por exemplo, pode modelar um fabricante com, no máximo, um automóvel como uma relação entre si.
Para definir uma propriedade de relacionamento entre um, especifique o nome do tipo de objeto relacionado como o tipo de propriedade.
Importante
Relacionamentos um-para-um devem ser opcionais
Quando você declara um relacionamento um-para-um no modelo de objeto, ele deve ser uma propriedade opcional. Se você tentar tornar um relacionamento um-para-um obrigatório, o Realm lançará uma exceção em tempo de execução.
O esquema de objeto Manufacturer
a seguir especifica que um fabricante pode ou não fazer um único Car
. Se eles fizerem um Car
, o Realm vinculará a ele através da propriedade car
:
class Manufacturer extends Realm.Object { static schema = { name: "Manufacturer", properties: { _id: "objectId", // A manufacturer that may have one car car: "Car?", }, }; } class Car extends Realm.Object { static schema = { name: "Car", properties: { _id: "objectId", make: "string", model: "string", miles: "int?", }, }; }
Definir uma propriedade de relacionamento um-para-muitos
Uma relação para-muitos mapeia uma propriedade para zero ou mais instâncias de outro tipo de objeto. Por exemplo, você pode modelar um fabricante com qualquer número de carros como uma relação para-muitos.
Para definir uma propriedade de relacionamento entre muitos, especifique o nome do tipo de objeto relacionado como uma lista.
Um aplicativo poderia usar os seguintes esquemas de objeto para indicar que um Manufacturer
pode criar vários objetos Car
, incluindo-os em sua propriedade cars
:
class Manufacturer extends Realm.Object { static schema = { name: "Manufacturer", properties: { _id: "objectId", // A manufacturer that may have many cars cars: "Car[]", }, }; } class Car extends Realm.Object { static schema = { name: "Car", properties: { _id: "objectId", make: "string", model: "string", miles: "int?", }, }; }
Definir uma propriedade de relacionamento inversa
Uma propriedade relacionamento inverso é um relacionamento de backlink automático. O Realm atualiza automaticamente os relacionamentos implícitos sempre que um objeto é adicionado ou removido em uma lista de itens correspondentes. Você não pode definir manualmente o valor de uma propriedade de relacionamento inversa.
Para definir uma propriedade de relacionamento inversa, configure o tipo de propriedade para linkingObjects
e especifique o tipo de objeto e o nome da propriedade que define o relacionamento para inverter.
Um aplicativo poderia usar os seguintes esquemas de objetos para indicar que um Manufacturer
pode criar muitos objetos Car
e que cada Car
deve controlar automaticamente qual Manufacturer
o cria.
- A propriedade
Manufacturer
do objetocars
é definida como uma relação entre muitos - com
Car
objetos e contém todos os carros de um determinado fabricante.
- A propriedade
- A propriedade
Car
do objetoassignee
inverte a relação e - atualizações automáticas para referir-se a qualquer objecto
Manufacturer
que contenha o veículo na sua propriedadecars
.
- A propriedade
class Manufacturer extends Realm.Object { static schema = { name: "Manufacturer", properties: { _id: "objectId", // A manufacturer that may have many cars cars: "Car[]", }, }; } class Car extends Realm.Object { static schema = { name: "Car", properties: { _id: "objectId", make: "string", model: "string", miles: "int?", // Backlink to the manufacturer. This is automatically updated whenever // this car is added to or removed from a manufacturer's cars list. assignee: { type: "linkingObjects", objectType: "Manufacturer", property: "cars", }, }, }; }
Definir uma propriedade de objeto embarcado
Para definir um modelo de objeto de Realm com um objeto incorporado (objeto de Realm aninhado), defina embedded
como true
.
Existe um objeto incorporado como dados aninhados dentro de um único objeto principal específico. Ele herda o ciclo de vida de seu objeto principal e não pode existir como um objeto de Realm independente. O Realm exclui automaticamente os objetos incorporados se o objeto principal for excluído ou quando for substituído por uma nova instância de objeto incorporado. Objetos incorporados não podem ter uma chave primária.
Você pode referenciar um tipo de objeto incorporado a partir de tipos de objeto principal da mesma maneira que um relacionamento.
O exemplo seguinte exige dois esquemas principais, Manufacturer
e Car
. O aplicativo requer um esquema secundário incorporado Warranty
. Um objeto Manufacturer
pode incorporar uma lista de objetos Warranty
, enquanto um objeto Car
só pode incorporar um único objeto Warranty
.
class Manufacturer extends Realm.Object { static schema = { name: "Manufacturer", properties: { _id: "objectId", name: "string", // Embed an array of objects warranties: { type: "list", objectType: "Warranty" }, }, }; } class Car extends Realm.Object { static schema = { name: "Car", properties: { _id: "objectId", make: "string", model: "string", miles: "int?", // Embed one object warranty: "Warranty", }, }; } class Warranty extends Realm.Object { static schema = { name: "Warranty", embedded: true, properties: { name: "string", termLength: "int", cost: "int", }, }; }
Definir um objeto assimétrico
Alterado na versão 12.2.1.
Se você estiver utilizando o Flexible Sync e precisar sincronizar uma coleção de forma unidirecional do seu dispositivo para o seu banco de dados do Atlas, configure a propriedade asymmetric
no seu esquema de objetos.
class WeatherSensor extends Realm.Object { static schema = { name: "WeatherSensor", // Sync WeatherSensor objects one way from your device // to your Atlas database. asymmetric: true, primaryKey: "_id", properties: { _id: "objectId", deviceId: "string", temperatureInFahrenheit: "int", barometricPressureInHg: "float", windSpeedInMph: "float", }, }; }
class WeatherSensor extends Realm.Object<WeatherSensor> { _id!: Realm.BSON.ObjectId; deviceId!: string; temperatureInFahrenheit!: number; barometricPressureInHg!: number; windSpeedInMph!: number; static schema: ObjectSchema = { name: "WeatherSensor", // sync WeatherSensor objects one way from your device // to your Atlas database. asymmetric: true, primaryKey: "_id", properties: { _id: "objectId", deviceId: "string", temperatureInFahrenheit: "int", barometricPressureInHg: "float", windSpeedInMph: "float", }, }; }
Nas versões 12.2.0 e anteriores do SDK do Node.js, não é possível criar vínculos de objetos assimétricos a tipos Realm.Object
. Nas versões 12.2.1 e posteriores do SDK, objetos assimétricos podem se vincular a tipos Realm.Object
, além de objetos embarcados.
Observação
Tentando ler objetos assimétricos
Objetos assimétricos não podem ser lidos. Se você tentar executar uma query de um objeto assimétrico, receberá o seguinte erro: "Erro: Não é possível executar uma query de classes assimétricas.".
Para saber mais sobre a ingestão de dados, leia Otimizar a sincronização com a ingestão de dados.
Definir dados não estruturados
Novidades na versão 12.9.0.
A partir da versão 12.9.0 do Node.js SDK , você pode armazenar collections de dados mistos dentro de uma propriedade mixed
. Você pode usar esse recurso para modelar estruturas de dados complexas, como documentos JSON ou MongoDB , sem precisar definir um modelo de dados rigoroso.
Dados não estruturados são dados que não estão em conformidade com facilmente um esquema esperado, tornando difícil ou impraticável modelar classes de dados individuais. Por exemplo, seu aplicativo pode ter dados altamente variáveis ou dados dinâmicos cuja estrutura é desconhecida no tempo de execução.
O armazenamento de coleções em uma propriedade mista oferece flexibilidade sem sacrificar a funcionalidade, incluindo sincronização de desempenho ao usar o Device Sync. E você pode trabalhar com eles da mesma forma que faria com uma collection não mista:
Você pode aninhar collections mistas em até 100 níveis.
Você pode consultar e React a alterações em coleções mistas.
Você pode localizar e atualizar elementos individuais de coleção mista.
No entanto, armazenar dados em coleções mistas é menos eficiente do que usar um esquema estruturado ou serializar blobs JSON em uma única propriedade de string.
Para modelar dados não estruturados em seu aplicativo, defina as propriedades apropriadas em seu esquema como tipos mistos . Você pode então definir essas propriedades mixed
como uma lista ou uma coleção de dicionário de elementos mistos. Observe que mixed
não pode representar um conjunto ou um objeto incorporado.
Dica
Use um mapa de tipos de dados mistos quando o tipo for desconhecido, mas cada valor terá um identificador exclusivo.
Use uma lista de tipos de dados mistos quando o tipo for desconhecido, mas a ordem dos objetos for significativa.