★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公衆號:山青詠芝(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: