★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(shanqingyongzhi)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:http://www.javashuo.com/article/p-envwuhom-gc.html
➤若是连接不是山青咏芝的博客园地址,则多是爬取做者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持做者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★javascript
按照下面的安装说明经过npm安装Realm JavaScript ,或者在GitHub上查看源代码。html
先决条件java
安装node
建立一个新的React Native项目:react
react-native init <project-name>
将目录更改成新项目(cd <project-name>
)并添加realm
依赖项:linux
npm install --save realm
接下来,将项目连接到本realm
机模块。android
react-native link realm
Android警告:根据版本的不一样,react-native link
可能会生成无效配置,正确更新Gradle(android/settings.gradle
和android/app/build.gradle
)但没法添加Realm模块。确认react-native link
已添加Realm模块; 若是没有,请使用如下步骤手动连接到库:ios
将如下行添加到android/settings.gradle
:git
include ':realm' project(':realm').projectDir = new File(rootProject.projectDir, '../node_modules/realm/android')
将Realm添加到依赖项中android/app/build.gradle
:github
// When using Android Gradle plugin 3.0 or higher dependencies { implementation project(':realm') } // When using Android Gradle plugin lower than 3.0 dependencies { compile project(':realm') }
添加导入并连接包MainApplication.java
:
import io.realm.react.RealmReactPackage; // add this import public class MainApplication extends Application implements ReactApplication { @Override protected List<ReactPackage> getPackages() { return Arrays.<ReactPackage>asList( new MainReactPackage(), new RealmReactPackage() // add this line ); } }
你如今准备好了。要查看Realm的运行状况,请将class <project-name>
如下内容替换为如下内容App.js
:
const Realm = require('realm'); class <project-name> extends Component { constructor(props) { super(props); this.state = { realm: null }; } componentWillMount() { Realm.open({ schema: [{name: 'Dog', properties: {name: 'string'}}] }).then(realm => { realm.write(() => { realm.create('Dog', {name: 'Rex'}); }); this.setState({ realm }); }); } render() { const info = this.state.realm ? 'Number of dogs in this Realm: ' + this.state.realm.objects('Dog').length : 'Loading...'; return ( <View style={styles.container}> <Text style={styles.welcome}> {info} </Text> </View> ); } }
而后,您能够在设备和模拟器中运行您的应用程序。
请注意,世博会不支持Realm,create-react-native-app
不起做用。
Realm JavaScript使您可以以安全,持久和快速的方式有效地编写应用程序的模型层。它旨在与React Native和Node.js一块儿使用。
这是一个简单的例子:
const Realm = require('realm'); // Define your models and their properties const CarSchema = { name: 'Car', properties: { make: 'string', model: 'string', miles: {type: 'int', default: 0}, } }; const PersonSchema = { name: 'Person', properties: { name: 'string', birthday: 'date', cars: 'Car[]', picture: 'data?' // optional property } }; Realm.open({schema: [CarSchema, PersonSchema]}) .then(realm => { // Create Realm objects and write to local storage realm.write(() => { const myCar = realm.create('Car', { make: 'Honda', model: 'Civic', miles: 1000, }); myCar.miles += 20; // Update a property value }); // Query Realm for all cars with a high mileage const cars = realm.objects('Car').filtered('miles > 1000'); // Will return a Results object with our 1 car cars.length // => 1 // Add another car realm.write(() => { const myCar = realm.create('Car', { make: 'Ford', model: 'Focus', miles: 2000, }); }); // Query results are updated in realtime cars.length // => 2 }) .catch(error => { console.log(error); });
请注意,若是要将Realm用于服务器端/节点,则能够在Realm Object Server文档中找到其余信息。
Realm Studio是咱们的首选开发人员工具,能够轻松管理Realm数据库和Realm平台。使用Realm Studio,您能够打开和编辑本地和同步的域,并管理任何Realm Object Server实例。它支持Mac,Windows和Linux。
只需open
在Realm
类上调用静态方法便可打开Realm 。传递配置对象。咱们已经看到这已经在示例中使用了包含schema
密钥的配置对象:
// Get the default Realm with support for our objects Realm.open({schema: [Car, Person]}) .then(realm => { // ...use the realm instance here }) .catch(error => { // Handle the error here if something went wrong });
有关配置对象的完整详细信息,请参阅API参考以获取配置。除此以外schema
,该对象的一些更常见的键包括:
path
:指定另外一个Realm的路径migration
:迁移功能sync
:一个同步对象,用于打开与Realm Object Server同步的RealminMemory
:Realm将在内存中打开,而且对象不会被持久化; 一旦最后一个Realm实例关闭,全部对象都会消失deleteRealmIfMigrationNeeded
:若是须要迁移,删除领域; 这在开发中颇有用,由于数据模型可能常常更改您可能已经注意到在前面的全部示例中都省略了path参数。在这种状况下,使用默认的Realm路径。您可使用Realm.defaultPath
全局属性访问和更改默认的Realm路径。
您是否但愿使用Realm Mobile Platform同步全部Realm数据库?全部与同步相关的文档已移至咱们的平台文档中
在不一样位置持有多个领域有时颇有用。例如,除了主Realm以外,您可能但愿将一些数据与应用程序捆绑在Realm文件中。您能够经过path
在初始化领域时指定参数来完成此操做。全部路径都相对于应用程序的可写文档目录:
// Open a realm at another path Realm.open({ path: 'anotherRealm.realm', schema: [CarSchema] }).then(/* ... */);
打开Realm时可用的另外一个选项是schemaVersion
属性。省略时,schemaVersion
属性默认为0
。您须要指定schemaVersion
什么时候使用包含与先前规范不一样的对象的模式初始化现有Realm。若是架构已更新且架构未更新,schemaVersion
则会引起异常。
const PersonSchema = { name: 'Person', properties: { name: 'string' } }; // schemaVersion defaults to 0 Realm.open({schema: [PersonSchema]});
若是你稍后再作这样的事情:
const UpdatedPersonSchema = { // The schema name is the same, so previous `Person` object // in the Realm will be updated name: 'Person', properties: { name: 'string', dog: 'Dog' // new property } }; // this will throw because the schema has changed // and `schemaVersion` is not specified Realm.open({schema: [UpdatedPersonSchema]}); // this will succeed and update the Realm to the new schema Realm.open({schema: [UpdatedPersonSchema], schemaVersion: 1});
若是要检索Realm的当前架构版本,可使用该Realm.schemaVersion
方法执行此操做。
const currentVersion = Realm.schemaVersion(Realm.defaultPath);
您能够经过简单地调用构造函数并将配置对象传递给它来建立领域实例。一般不推荐这样作,由于它会阻塞而且多是一个耗时的操做,特别是若是要运行迁移或者域同步而且您不但愿在数据彻底下载以前冒险修改数据。
若是您仍想这样作,模式很简单:
const realm = new Realm({schema: [PersonSchema]}); // You can now access the realm instance. realm.write(/* ... */);
领域数据模型由初始化期间传递到Realm的架构信息定义。对象的模式由对象name
和一组属性组成。每一个属性具备名称和由或包含属性的类型的字符串,或与对象描述name
,type
,objectType
,optional
,default
,和indexed
字段。
const Realm = require('realm'); const CarSchema = { name: 'Car', properties: { make: 'string', model: 'string', miles: {type: 'int', default: 0}, } }; const PersonSchema = { name: 'Person', properties: { name: 'string', birthday: 'date', cars: 'Car[]' picture: 'data?', // optional property } }; // Initialize a Realm with Car and Person models Realm.open({schema: [CarSchema, PersonSchema]}) .then(realm => { // ... use the realm instance to read and modify data })
此时,经过类定义模型的支持是有限的。它在React Native中工做,但在Node中不工做。
若是要使用ES2015类(而且可能但愿继承现有功能),则只需在构造函数上定义模式:
class Person { get fullName() { return this.firstName + ' ' + this.lastName; } } Person.schema = { name: 'Person', properties: { firstName: 'string', lastName: 'string' } };
您如今能够将类自己传递给schema
打开配置的属性:
Realm.open({schema: [Person]}) .then( /* ... */ );
您能够一直访问属性:
realm.write(() => { const john = realm.create('Person', { firstName: 'John', lastName: 'Smith' }); john.lastName = 'Peterson'; console.log(john.fullName); // -> 'John Peterson' });
域支持下列基本类型:bool
,int
,float
,double
,string
,data
,和date
。
bool
属性映射到JavaScript boolean
值int
,, float
和double
属性映射到JavaScript number
值。内部'int'和'double'存储为64位,而float
存储为32位。string
属性映射到 string
data
属性映射到 ArrayBuffer
date
属性映射到 Date
将基本属性指定为速记时,您能够仅指定类型,而没必要指定具备单个条目的字典:
const CarSchema = { name: 'Car', properties: { // The following property types are equivalent make: {type: 'string'}, model: 'string', } }
默认状况下,基本类型是非可选的,不支持存储null
或undefined
。经过optional
在属性定义中指定指示符或使用简写语法,经过?
在类型名称后附加a ,可使属性成为可选:
const PersonSchema = { name: 'Person', properties: { realName: 'string', // required property displayName: 'string?', // optional property birthday: {type: 'date', optional: true}, // optional property } }; let realm = new Realm({schema: [PersonSchema, CarSchema]}); realm.write(() => { // optional properties can be set to null or undefined at creation let charlie = realm.create('Person', { realName: 'Charlie', displayName: null, // could also be omitted entirely birthday: new Date(1995, 11, 25), }); // optional properties can be set to `null`, `undefined`, // or to a new non-null value charlie.birthday = undefined; charlie.displayName = 'Charles'; // Setting a non-optional property to null will throw `TypeError` // charlie.realName = null; });
除了存储单个值以外,还能够将属性声明为任何支持的基本类型的列表。这是经过附加[]
类型名称来完成的:
const PersonSchema = { name: 'Person', properties: { name: 'string', testScores: 'double?[]' } }; let realm = new Realm({schema: [PersonSchema, CarSchema]}); realm.write(() => { let charlie = realm.create('Person', { name: 'Charlie', testScores: [100.0] }); // Charlie had an excused absense for the second test and was allowed to skip it charlie.testScores.push(null); // And then he didn't do so well on the third test charlie.testScores.push(70.0); });
访问列表属性时,将List
返回一个对象。List
具备与常规JavaScript数组很是类似的方法。最大的区别在于对a所作的任何更改都会List
自动保存到底层Realm,所以它们只能在写入事务中进行修改。此外,List
s属于从中获取的基础对象 - 您只能List
经过从拥有对象访问属性来获取实例,而且没法手动建立它们。
虽然list属性中的值能够是可选的,但list属性自己不能。optional
使用longhand语法(values: {type: 'int[]', optional: true}
)指定list属性将使列表中的值可选。
对于一对一关系,您能够将name
要引用的对象模式的属性指定为属性的类型:
const PersonSchema = { name: 'Person', properties: { // The following property definitions are equivalent car: {type: 'Car'}, van: 'Car', } };
使用对象属性时,须要确保全部引用的类型都存在于用于打开Realm的模式中:
// CarSchema is needed since PersonSchema contains properties of type 'Car' Realm.open({schema: [CarSchema, PersonSchema]}) .then(/* ... */);
访问对象属性时,可使用常规属性语法访问嵌套属性:
realm.write(() => { const nameString = person.car.name; person.car.miles = 1100; // create a new Car by setting the property to an object // with all of the required fields person.van = {make: 'Ford', model: 'Transit'}; // set both properties to the same car instance person.car = person.van; });
Realm中的对象属性始终是可选的,没必要明确指定,也不能使其成为必需属性。
与基本属性同样,您也可使用对象列表来造成多对多关系。这能够经过附加[]
到目标对象模式的名称,或者经过将属性类型设置为list
并指定objectType
:
const PersonSchema = { name: 'Person', properties: { // The following property definitions are equivalent cars: {type: 'list', objectType: 'Car'}, vans: 'Car[]' } } let carList = person.cars; // Add new cars to the list realm.write(() => { carList.push({make: 'Honda', model: 'Accord', miles: 100}); carList.push({make: 'Toyota', model: 'Prius', miles: 200}); }); let secondCar = carList[1].model; // access using an array index
与其余列表和一对一关系不一样,多对多关系不能是可选的。
连接是单向的。所以,若是to-many属性Person.dogs
连接到Dog
实例而且Dog.owner
连接到一个属性Person
,则这些连接彼此独立。将a 的属性附加Dog
到Person
实例的dogs
属性不会自动将dog的owner
属性设置为this Person
。由于手动同步关系对是容易出错,复杂和重复的信息,因此Realm提供连接对象属性来表示这些反向关系。
经过连接对象属性,您能够从特定属性获取连接到给定对象的全部对象。例如,一个Dog
对象能够拥有一个名为的属性owners
,该属性包含在其属性Person
中具备此确切Dog
对象的全部对象dogs
。这是经过建立owners
类型的属性linkingObjects
而后指定它与Person
对象的关系来完成的。
const PersonSchema = { name: 'Person', properties: { dogs: 'Dog[]' } } const DogSchema = { name:'Dog', properties: { // No shorthand syntax for linkingObjects properties owners: {type: 'linkingObjects', objectType: 'Person', property: 'dogs'} } }
甲linkingObjects
属性能够指向到一个List
属性(一对多的关系)或Object
属性(对一的关系):
const ShipSchema = { name: 'Ship', properties: { captain: 'Captain' } } const CaptainSchema = { name: 'Captain', properties: { ships: {type: 'linkingObjects', objectType: 'Ship', property: 'captain'} } }
访问linkingObjects
属性时,将Results
返回一个对象,所以彻底支持进一步的查询和排序。linkingObject
属性属于从中获取的对象,没法直接设置或操做。它们在提交事务时自动更新。
访问linkingObjects
没有模式:若是你已经打开了一个域文件没有指定一个模式,例如在一个领域的功能回调,你能够获得一个linkingObjects
经过调用属性linkingObjects(objectType, property)
上的Object
实例:
let captain = realm.objectForPrimaryKey('Captain', 1); let ships = captain.linkingObjects('Ship', 'captain');
连接对象属性不能是可选的。
能够经过default
在属性定义中设置指示符来指定默认属性值。要使用默认值,请在对象建立期间保留未指定的属性。
const CarSchema = { name: 'Car', properties: { make: {type: 'string'}, model: {type: 'string'}, drive: {type: 'string', default: 'fwd'}, miles: {type: 'int', default: 0} } }; realm.write(() => { // Since `miles` is left out it defaults to `0`, and since // `drive` is specified, it overrides the default value realm.create('Car', {make: 'Honda', model: 'Accord', drive: 'awd'}); });
您能够indexed
向属性定义添加指示符以使该属性编入索引。这是支持的int
,string
,bool
,和date
物业类型:
var BookSchema = { name: 'Book', properties: { name: { type: 'string', indexed: true }, price: 'float' } };
索引属性将极大地加速查询,其中以较慢的插入为代价比较属性的相等性。
您能够primaryKey
在对象模型string
和int
属性中指定属性。声明主键能够有效地查找和更新对象,并为每一个值强制实现惟一性。将具备主键的对象添加到Realm后,没法更改主键。
const BookSchema = { name: 'Book', primaryKey: 'id', properties: { id: 'int', // primary key title: 'string', price: 'float' } };
主键属性会自动编入索引。
对领域中对象的更改 - 建立,更新和删除 - 必须在write()
事务块中进行。请注意,写入事务具备不可忽略的开销; 您应该尽可能减小write
代码中的块数。
使用如下create
方法建立对象:
try { realm.write(() => { realm.create('Car', {make: 'Honda', model: 'Accord', drive: 'awd'}); }); } catch (e) { console.log("Error on creation"); }
请注意,抛出的任何异常都write()
将取消该事务。该try/catch
块不会在全部示例中显示,但这是一种很好的作法。
若是对象具备对象属性,则能够经过为每一个子属性指定JSON值来递归地建立这些属性的值:
realm.write(() => { realm.create('Person', { name: 'Joe', // nested objects are created recursively car: {make: 'Honda', model: 'Accord', drive: 'awd'}, }); });
您能够经过在写入事务中设置其属性来更新任何对象。
realm.write(() => { car.miles = 1100; });
若是模型类包含主键,则可让Realm根据其主键值智能地更新或添加对象。这是经过将true
第三个参数传递给create
方法来完成的:
realm.write(() => { // Create a book object realm.create('Book', {id: 1, title: 'Recipes', price: 35}); // Update book with new price keyed off the id realm.create('Book', {id: 1, price: 55}, true); });
在上面的示例中,因为对象已经存在id
,1
而且咱们已经true
为第三个参数传入了值,所以更新price属性而不是尝试建立新对象。因为title
省略了该属性,所以该对象保留此属性的原始值。请注意,在建立或更新具备主键属性的对象时,必须指定主键。
能够经过delete
在写入事务中调用方法来删除对象。
realm.write(() => { // Create a book object let book = realm.create('Book', {id: 1, title: 'Recipes', price: 35}); // Delete the book realm.delete(book); // Delete multiple books by passing in a `Results`, `List`, // or JavaScript `Array` let allBooks = realm.objects('Book'); realm.delete(allBooks); // Deletes all books });
查询容许您从Realm获取单个类型的对象,并可选择过滤和排序这些结果。全部查询(包括查询和属性访问)在Realm中都是惰性的。只有在访问对象和属性时才会读取数据。这容许您以高效的方式表示大量数据。
执行查询时,会返回一个Results
对象。结果只是您的数据视图,而且不可变。
从Realm中检索对象的最基本方法是使用a上的objects
方法Realm
获取给定类型的全部对象:
let dogs = realm.objects('Dog'); // retrieves all Dogs from the Realm
您能够Results
经过filtered
在a List
或a Results
上使用查询字符串调用方法来进行过滤。
例如,如下内容将更改咱们以前的示例,以检索全部颜色为棕褐色且名称以“B”开头的狗:
let dogs = realm.objects('Dog'); let tanDogs = dogs.filtered('color = "tan" AND name BEGINSWITH "B"');
Realm支持的查询语言受到Apple的NSPredicate的启发。让咱们简要总结一下支持的功能和语法:
false
,true
和null
。YYYY-MM-DD@HH:MM:SS:NANOSECONDS
而且YYYY-MM-DDTHH:MM:SS:NANOSECONDS
能够省略纳秒。=
/ ==
,<=
,<
,>=
,>
,和!=
/ <>
都支持int
,float
,double
,和Date
物业类型,例如age = 45
。=
/ ==
和!=
/ 。<>
bool
ArrayBuffer
)的属性,所述=
(和==
), !=
(和<>
), ,BEGINSWITH
,CONTAINS
和ENDSWITH
运营商都支持,例如name CONTAINS 'Ja'
。LIKE
运算符的字符串,能够进行通配符比较,例如name LIKE '*an?'
匹配“Jane”,“Dan”,“Shane”等。[c]
例如字符串的字符串不区分大小写的比较CONTAINS[c] 'Ja'
。请注意,只有字符“AZ”和“az”才会被忽略。AND
/ &&
,OR
/ ||
和NOT
/ !
,例如name BEGINSWITH 'J' AND age >= 32
。@count
/ @size
,@min
,@max
,@sum
而且@avg
都支持列表属性,如employees.@count > 5
发现有更多的5个元素员工的清单。@count
/ @size
,例如name.@size = 5
,查找名称为5个字母的全部字符串。child.age >= 13
和cars.@avg.milage > 1000
。parents.age > 25
和parents.@count == 2
。$
操做者可用于替代参数,例如child.age >= $0
(见下面的示例)。SORT
和DISTINCT
如age > 20 SORT(name ASC, age DESC) DISTINCT(name)
。
ASC
,ASCENDING
,DESC
,DESCENDING
。关于如何查询Realm的一个很是重要的例子是:
const Realm = require('realm'); const CarSchema = { name: 'Car', properties: { make: 'string', model: 'string', miles: {type: 'int', default: 0}, } }; const PersonSchema = { name: 'Person', properties: { name: 'string', cars: {type: 'list', objectType: 'Car'}, } }; // Initialize a Realm with Car and Person models Realm.open({schema: [CarSchema, PersonSchema]}) .then(realm => { // Add persons and their cars realm.write(() => { let john = realm.create('Person', {name: 'John', cars: []}); john.cars.push({make: 'Honda', model: 'Accord', miles: 1500}); john.cars.push({make: 'Toyota', model: 'Prius', miles: 2780}); let joan = realm.create('Person', {name: 'Joan', cars: []}); joan.cars.push({make: 'Skoda', model: 'Octavia', miles: 1120}); joan.cars.push({make: 'Ford', model: 'Fiesta', miles: 95}); joan.cars.push({make: 'VW', model: 'Golf', miles: 1270}); let jill = realm.create('Person', {name: 'Jill', cars: []}); let jack = realm.create('Person', {name: 'Jack', cars: