定义 Realm 对象模型 - React Native SDK
定义对象类型
要定义 Realm 对象类型,请创建一个扩展 Realm.Object
的类。在静态属性 name
中定义类型的 properties
和 schema
。在 Realm 中的对象类型中,该类型的名称必须是唯一的。
class Book extends Realm.Object { static schema = { name: 'Book', properties: { name: {type: 'string', indexed: true}, price: 'int?', }, }; }
class Book extends Realm.Object<Book> { name!: string; price?: number; static schema: ObjectSchema = { name: 'Book', properties: { name: {type: 'string', indexed: true}, price: 'int?', }, }; }
然后,您可以在打开域时将类本身传递给配置对象的模式属性。
支持的属性类型
Realm 对象中的每个属性都有一个明确定义的数据类型。属性的类型可以是原始数据类型,也可以是在同一个 Realm 中定义的对象类型。类型还指定了属性是包含单个值还是包含值的列表。
要指定字段包含原始值类型的列表,请在类型名称后面添加 []
。
有关支持的属性类型的列表,请参阅属性类型
定义对象属性
要定义对象类型的属性,请在properties
字段下创建表示属性名称和数据类型的键值对。
以下模式定义了具有以下属性的 Car
类型:_id
make
、model
和 miles
。
声明可选属性
要将属性标记为可选,请使用对象语法并将 optional
设置为 true
。您还可以使用简化的语法:将问号 ?
附加到类型。这最适合基本类型。对于更复杂的类型,应使用更具体的对象语法。
在下面的 Person
类示例中,age
和 birthday
属性都是可选的。
class Person extends Realm.Object<Person> { name!: string; age?: number; birthday?: Date; static schema: ObjectSchema = { name: 'Person', properties: { name: 'string', age: { type: 'int', optional: true, }, // You can use a simplified syntax instead. For // more complicated types, use the object syntax. birthday: 'date?', }, }; }
声明主键
要将某个属性指定为对象类型的主键,请将模式的 primaryKey
字段设置为属性名称。
注意
主键是唯一标识对象的属性。 Realm 会自动对主键属性进行索引,这允许您根据主键高效地读取和修改对象。
如果某个对象类型具有主键,则该类型的所有对象都必须包含主键属性,并且在 Realm 中相同类型的对象中,该主键属性具有唯一值。一个对象类型只能有一个主键。将某个对象类型的任何对象添加到 Realm 后,您无法更改该对象类型的主键属性,也无法修改对象的主键值。
在以下 Task
类的示例中,我们将 _id
属性指定为主键。
1 class Task extends Realm.Object { 2 static schema = { 3 name: 'Task', 4 properties: { 5 _id: 'int', 6 name: 'string', 7 priority: 'int?', 8 progressMinutes: 'int?', 9 assignee: 'Person?', 10 }, 11 primaryKey: '_id', 12 }; 13 }
1 class Task extends Realm.Object<Task> { 2 _id!: number; 3 name!: string; 4 priority?: number; 5 progressMinutes?: number; 6 assignee?: Person; 7 age?: number; 8 9 static schema: ObjectSchema = { 10 name: 'Task', 11 properties: { 12 _id: 'int', 13 name: 'string', 14 priority: 'int?', 15 progressMinutes: 'int', 16 assignee: 'Person?', 17 }, 18 primaryKey: '_id', 19 }; 20 }
为属性创建索引
如果经常根据特定属性执行读取操作,则可以为该属性建立索引以优化性能。Realm 支持为字符串、整数、布尔值、Date
、UUID
和 ObjectId
属性建立索引。
注意
索引显著提高了某些读取操作的速度,但代价是写入速度略微下降,并增加了存储和内存开销。Realm 将索引存储在磁盘上,这会使您的 Realm 文件更大。每个索引条目至少有 12 个字节。索引条目的排序支持高效的相等匹配和基于范围的查询操作。
要为给定属性建立索引,请将该属性的 indexed
字段设置为 true
。
在以下 Book
类的示例中,我们在 name
属性上定义了一个索引。
1 class Book extends Realm.Object { 2 static schema = { 3 name: 'Book', 4 properties: { 5 name: {type: 'string', indexed: true}, 6 price: 'int?', 7 }, 8 }; 9 }
1 class Book extends Realm.Object<Book> { 2 name!: string; 3 price?: number; 4 5 static schema: ObjectSchema = { 6 name: 'Book', 7 properties: { 8 name: {type: 'string', indexed: true}, 9 price: 'int?', 10 }, 11 }; 12 }
设置全文搜索索引
除了标准索引外,Realm 还支持对字符串属性创建 Atlas 全文搜索索引。虽然无论是否使用标准索引都可以查询字符串字段,但 FTS 索引支持搜索多个词汇和短语并排除其他。
有关查询 FTS 索引的更多信息,请参阅使用全文搜索进行筛选。
要创建 FTS 索引,请将索引类型设置为'full-text'
。 这将启用对该属性的全文查询。 在以下示例中,我们将name
属性的索引类型设置为'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?', }, }; }
设置默认属性值
要定义默认值,请将属性值设置为具有 type
字段和 default
字段的对象。
在以下 Car
类的示例中,我们定义了一个默认值为 0
的 miles
属性。
11.1.0 版新增功能。
在 Realm.js v11.1.0 及更高版本中,您可以使用函数来定义动态默认值,例如下例中的 timestamp
属性。
1 class Car extends Realm.Object { 2 static schema = { 3 name: 'Car', 4 properties: { 5 make: 'string', 6 model: 'string', 7 miles: {type: 'int', default: 0}, 8 timestamp: { 9 type: 'int', 10 default: () => Math.round(new Date().getTime() / 1000), 11 }, 12 }, 13 }; 14 }
1 class Car extends Realm.Object { 2 make!: string; 3 model!: string; 4 miles: number = 0; 5 timestamp: number = Math.round(new Date().getTime() / 1000); 6 7 static schema: ObjectSchema = { 8 name: 'Car', 9 properties: { 10 make: 'string', 11 model: 'string', 12 miles: {type: 'int', default: 0}, 13 timestamp: { 14 type: 'int', 15 default: () => Math.round(new Date().getTime() / 1000), 16 }, 17 }, 18 }; 19 }
重新映射属性
要在代码中使用与 Realm 中存储的属性名称不同的属性名称,请将 mapTo
设置为代码中显示的属性名称。
在以下 Employee
类的示例中,我们将 first_name
属性重映射到 firstName
。
1 class Employee extends Realm.Object { 2 static schema = { 3 name: 'Employee', 4 properties: { 5 _id: 'string', 6 first_name: {type: 'string', mapTo: 'firstName'}, 7 }, 8 primaryKey: '_id', 9 }; 10 }
1 class Employee extends Realm.Object { 2 _id!: string; 3 first_name!: string; 4 5 static schema: ObjectSchema = { 6 name: 'Employee', 7 properties: { 8 _id: 'string', 9 first_name: {type: 'string', mapTo: 'firstName'}, 10 }, 11 primaryKey: '_id', 12 }; 13 }
定义非对称对象
如果您使用 Flexible Sync 并且需要将集合从设备单向同步到 Atlas 数据库,则可以在对象模式上设置 asymmetric
属性。
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', }, }; }
在版本 realm@12.2.1
中进行了更改。
在 JS SDK 版本 12.2.0 及更早版本中,您无法从非对称对象链接到 Realm.Object
类型。在 SDK 版本 12.2.1 及更高版本中,除了嵌入式对象以外,非对称对象还可以链接到 Realm.Object
类型。
注意
尝试读取非对称对象
无法读取非对称对象。如果尝试查询非对称对象,您将收到以下错误:“错误:无法查询非对称类。”
要了解有关数据导入的更多信息,请参阅将数据流式传输到 Atlas。
定义非结构化数据
realm@12.9.0
版本中的新增功能。
从JavaScript SDK 版本 12.9.0 开始, 您可以在mixed
属性中存储混合数据的集合。 您可以使用此功能对复杂的数据结构(例如JSON或MongoDB文档)进行建模,而无需定义严格的数据模型。
非结构化数据是指不容易符合预期模式的数据,因此对单个数据类进行建模很困难或不切实际。 示例,您的应用可能具有高度可变的数据或动态数据,其结构在运行时未知。
将集合存储在混合属性中可在不牺牲功能的情况下提供灵活性,包括使用Device Sync时的性能同步。 您可以像使用非混合集合一样使用它们:
您最多可以嵌套100级混合集合。
您可以对混合集合的React进行查询和响应。
您可以查找并更新单个混合集合元素。
但是,与使用结构化模式或将JSON blob 序列化为单个string属性相比,在混合集合中存储数据的性能较低。
要对应用中的非结构化数据进行建模,请在模式中将适当的属性定义为混合类型。 然后,您可以设立这些mixed
属性设置为混合元素的列表或字典集合。 请注意, mixed
属性不能保存设立或嵌入式对象。
提示
当类型未知但每个值都有唯一标识符时,请使用混合数据类型的映射。
当类型未知但对象的顺序有意义时,请使用混合数据类型的列表。
TypeScript 和必需属性
我们建议使用 Realm.create() 创建 Realm 对象 ,但您也可以对对象模型的类使用new
操作符。
如果您使用 new
,则在扩展 Realm.Object
时,必须将您的类作为泛型添加,并添加任何必需的属性。这将为您的对象模型提供完整的 TypeScript 支持,包括未定义必需字段时的类型错误。
class Book extends Realm.Object<Book, 'name' | 'store'> { name!: string; store!: string; price?: number; static schema: ObjectSchema = { name: 'Book', properties: { name: {type: 'string', indexed: true}, store: 'string', price: 'int?', }, }; }