简体   繁体   English

Realm是哪种数据库?

[英]What kind of db is Realm?

What kind of database is Realm ? Realm是哪种数据库? Is it ORM ? ORM吗? Or does it work like object database? 还是像对象数据库一样工作? Maybe database structure somehow affects design processes? 也许数据库结构以某种方式影响设计过程? Is there any nuances in designing Realm database? 设计Realm数据库是否有任何细微差别?

I'm asking here, because I haven't found any answers in official website 我在这里问,因为我在官方网站上找不到任何答案

Unfortunately I do not actually use the iOS version, but I do use the Android version, which day by day is more and more similar in its feature set to the iOS version, and they share the same core , and they are closer to providing the same unified behavior via the object-store . 不幸的是,我实际上并没有使用iOS版本,但是我使用的是Android版本,该功能在功能上与iOS版本越来越相似,并且它们具有相同的core ,并且它们更接近于提供通过object-store相同的统一行为。

Most of this answer will therefore be based on the Swift API docs. 因此,大多数答案将基于Swift API文档。 (Realm Swift 2.6.1) (Realm Swift 2.6.1)


Realm is by default an object store. 默认情况下,领域是对象存储。 Technically it stores your data in a schema, where the schema is defined by classes, like 从技术上讲,它将数据存储在一个架构中,该架构由类定义,例如

// from https://realm.io/docs/swift/latest/#models
class Person: Object {
    dynamic var name = ""
    dynamic var birthdate = NSDate(timeIntervalSince1970: 1)
    let dogs = List<Dog>()
}

Now what's interesting about Realm is that it is not a relational database; 现在,Realm的有趣之处在于它不是关系数据库。 it stores the objects directly. 它直接存储对象。 In fact, objects managed by Realm (aka obtained via a query to Realm, or a newly created object made by Realm) map directly to the underlying Realm file, and do not copy the data to fields, the accessors directly read from and write to the Realm file. 实际上,由Realm管理的对象(也可以通过对Realm的查询获得的对象,或者由Realm创建的新创建的对象)直接映射到底层Realm文件,并且不将数据复制到字段,访问器直接从中读取和写入领域文件。

This "direct access" results in that all data is loaded only when accessed (lazy-evaluation), therefore caching of managed objects is not needed(!). 这种“直接访问”导致仅在访问(延迟评估)时才加载所有数据,因此不需要对托管对象进行缓存(!)。

All writes are transactional. 所有写操作都是事务性的。 Outside of transactions, managed RealmObjects cannot be modified. 在事务之外,不能修改托管RealmObject。


Between your objects, you can have relationships (links): 在对象之间,可以具有关系 (链接):

// from https://realm.io/docs/swift/latest/#relationships
class Dog: Object {
    // ... other property declarations
    dynamic var owner: Person? // to-one relationships must be optional
}

class Person: Object {
    // ... other property declarations
    let dogs = List<Dog>() // to-many relationship
}

Any relationship (to-one, to-many) has their corresponding backlink , which you can define as "the objects that are linking to this object". 任何关系(一对一,一对多)都有其相应的backlink ,您可以将其定义为“链接到该对象的对象”。

// from https://realm.io/docs/swift/latest/#relationships
class Dog: Object {
    dynamic var name = ""
    dynamic var age = 0
    let owners = LinkingObjects(fromType: Person.self, property: "dogs")
}

Realm's managed objects are "live, immutable views of the data" (from here ), which mutate in place, and you receive change notification about it via a notification token (from here ). Realm的托管对象是“实时的,不可变的数据视图”(从此处开始 ),它们在适当位置发生了变化,您可以通过notification token (从此处接收有关该数据的更改通知 The same applies to any managed RealmObject , but also query results . 这适用于任何托管RealmObject ,但适用于查询结果

Meaning, query results are automatically asynchronously evaluated, and only elements accessed at a given index are read from the database, in a lazy-loaded manner! 意思是,查询结果是自动异步评估的,并且只能以延迟加载的方式从数据库中读取在给定索引下访问的元素! Therefore, pagination is not needed. 因此,不需要分页。

Any writes on any thread automatically send a notification to threads associated with a run-loop, and the query results are automatically updated, and the change listener (notification block) is called. 对任何线程的任何写操作都会自动向与运行循环关联的线程发送通知,查询结果将自动更新,并调用更改侦听器(通知块)。

// from https://realm.io/docs/swift/latest/#collection-notifications
  override func viewDidLoad() {
    super.viewDidLoad()
    let realm = try! Realm()
    let results = realm.objects(Person.self).filter("age > 5")

    // Observe Results Notifications
    notificationToken = results.addNotificationBlock { [weak self] (changes: RealmCollectionChange) in
      guard let tableView = self?.tableView else { return }
      switch changes {
      case .initial:
        // Results are now populated and can be accessed without blocking the UI
        tableView.reloadData()
        break
      case .update(_, let deletions, let insertions, let modifications):
        // Query results have changed, so apply them to the UITableView
        tableView.beginUpdates()
        tableView.insertRows(at: insertions.map({ IndexPath(row: $0, section: 0) }),
                           with: .automatic)
        tableView.deleteRows(at: deletions.map({ IndexPath(row: $0, section: 0)}),
                           with: .automatic)
        tableView.reloadRows(at: modifications.map({ IndexPath(row: $0, section: 0) }),
                           with: .automatic)
        tableView.endUpdates()
        break
      case .error(let error):
        // An error occurred while opening the Realm file on the background worker thread
        fatalError("\(error)")
        break
      }
    }
  }

  deinit {
    notificationToken?.stop()
  }

The most well-known limitation is that RealmObjects, RealmResults and Realms cannot be passed between threads . 最著名的限制是RealmObjects,RealmResults和Realms 不能在线程之间传递 (Other limitations are here ). (其他限制在这里 )。

A RealmObject/RealmResults/Realm on a given thread can only be accessed on the thread where its corresponding Realm instance was opened (read here ). 给定线程上的RealmObject / RealmResults / Realm只能在打开其相应Realm实例的线程上访问(请参见此处 )。 (The exception is RealmObjects sent between threads using ThreadSafeReference , see here ). (例外是使用ThreadSafeReference在线程之间发送的RealmObjects,请参见此处 )。

Therefore, background threads require their own Realm instance, generally wrapped in an autoreleasepool , see here . 因此,后台线程需要它们自己的Realm实例,通常将其包装在autoreleasepool ,请参见此处

// from https://realm.io/docs/swift/latest/#using-a-realm-across-threads
DispatchQueue(label: "background").async {
  autoreleasepool {
    // Get realm and table instances for this thread
    let realm = try! Realm()

    // Break up the writing blocks into smaller portions
    // by starting a new transaction
    for idx1 in 0..<1000 {
      realm.beginWrite()

      // Add row via dictionary. Property order is ignored.
      for idx2 in 0..<1000 {
        realm.create(Person.self, value: [
          "name": "\(idx1)",
          "birthdate": Date(timeIntervalSince1970: TimeInterval(idx2))
        ])
      }

      // Commit the write transaction
      // to make this data available to other threads
      try! realm.commitWrite()
    }
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM