Database
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Database

Bắt đầu với Cloud Firestore cho iOS

Các nhà lập trình di động đã tận dụng lợi thế của Google’s Mobile Backend as a Service (MBaaS) nền tảng Cơ sở dữ liệu thời gian thực Firebase trong nhiều năm, giúp họ tập trung vào việc xây dựng các tính năng cho ứng dụng của mình mà không phải lo lắng về cơ sở hạ tầng và cơ sở dữ liệu back-end. Bằng cách giúp dễ dàng lưu trữ và duy trì dữ liệu trên đám mây cũng như quan tâm đến xác thực và bảo mật, Firebase cho phép người viết mã tập trung vào phía máy khách.

Năm ngoái, Google đã công bố một giải pháp cơ sở dữ liệu back-end khác, Cloud Firestore, được xây dựng từ đầu với lời hứa về khả năng mở rộng và tính trực quan cao hơn. Tuy nhiên, điều này dẫn đến một số nhầm lẫn về vị trí của nó liên quan đến sản phẩm chủ lực hiện có của Google, Cơ sở dữ liệu thời gian thực của Firebase. Hướng dẫn này sẽ phác thảo sự khác biệt giữa hai nền tảng và những lợi thế riêng biệt của mỗi nền tảng. Bạn sẽ học cách làm việc với các tham chiếu tài liệu Firestore, cũng như đọc, ghi, cập nhật và xóa dữ liệu trong thời gian thực bằng cách xây dựng một ứng dụng nhắc nhở đơn giản.

Mục tiêu của Hướng dẫn này

Hướng dẫn này sẽ cho bạn thấy Cloud Firestore. Bạn sẽ học cách tận dụng nền tảng này để có được sự bền bỉ và đồng bộ hóa cơ sở dữ liệu trong thời gian thực. Chúng tôi sẽ đề cập đến các chủ đề sau:

  • Cloud Firestore là gì
  • mô hình dữ liệu Firestore
  • thiết lập Cloud Firestore
  • tạo và làm việc với các tham chiếu Cloud Firestore
  • đọc dữ liệu trong thời gian thực từ Cloud Firestore
  • tạo, cập nhật và xóa dữ liệu
  • lọc và truy vấn kết hợp

Kiến thức giả định

Hướng dẫn này giả định rằng bạn đã tiếp xúc với Firebase và có nền tảng phát triển với Swift và Xcode.

Cloud Firestore là gì?

Giống như Cơ sở dữ liệu thời gian thực của Firebase, Firestore cung cấp cho các nhà phát triển web và thiết bị di động giải pháp đám mây đa nền tảng để duy trì dữ liệu trong thời gian thực, bất kể độ trễ của mạng hoặc kết nối internet, cũng như tích hợp liền mạch với bộ sản phẩm Google Cloud Platform. Cùng với những điểm tương đồng này, có những ưu điểm và nhược điểm riêng biệt để phân biệt cái này với cái kia.

Mô hình dữ liệu

Ở cấp độ cơ bản, Cơ sở dữ liệu thời gian thực lưu trữ dữ liệu dưới dạng một cây JSON lớn, nguyên khối, phân cấp, trong khi Firestore tổ chức dữ liệu trong các tài liệu và bộ sưu tập, cũng như các bộ sưu tập con. Điều này yêu cầu ít chuẩn hóa hơn. Lưu trữ dữ liệu trong một cây JSON có lợi ích là sự đơn giản khi làm việc với các yêu cầu dữ liệu đơn giản; tuy nhiên, nó trở nên cồng kềnh hơn về quy mô khi làm việc với dữ liệu phân cấp phức tạp hơn.

Hỗ trợ ngoại tuyến

Cả hai sản phẩm đều cung cấp hỗ trợ ngoại tuyến, chủ động lưu vào bộ nhớ đệm dữ liệu trong hàng đợi khi có kết nối mạng tiềm ẩn hoặc không có — đồng bộ hóa các thay đổi cục bộ trở lại giao diện người dùng khi có thể. Firestore hỗ trợ đồng bộ hóa ngoại tuyến cho các ứng dụng web ngoài ứng dụng dành cho thiết bị di động, trong khi Cơ sở dữ liệu thời gian thực chỉ cho phép đồng bộ hóa trên thiết bị di động.

Truy vấn và Giao dịch

Cơ sở dữ liệu thời gian thực chỉ hỗ trợ khả năng sắp xếp và lọc có giới hạn — bạn chỉ có thể sắp xếp hoặc lọc ở cấp thuộc tính, chứ không phải cả hai, trong một truy vấn duy nhất. Các truy vấn cũng sâu, có nghĩa là chúng trả về một cây con lớn các kết quả trở lại. Sản phẩm chỉ hỗ trợ các hoạt động ghi và giao dịch đơn giản yêu cầu gọi lại hoàn thành.

Mặt khác, Firestore giới thiệu các truy vấn chỉ mục với sắp xếp và lọc kết hợp, cho phép bạn kết hợp các hành động để tạo bộ lọc chuỗi và sắp xếp. Bạn cũng có thể thực hiện các truy vấn cạn trả về các tập hợp con thay cho toàn bộ tập hợp mà bạn sẽ nhận được với Cơ sở dữ liệu thời gian thực. Các giao dịch có bản chất nguyên tử, cho dù bạn gửi một hoạt động hàng loạt hay đơn lẻ, với các giao dịch lặp lại tự động cho đến khi kết thúc. Ngoài ra, Cơ sở dữ liệu thời gian thực chỉ hỗ trợ các giao dịch ghi riêng lẻ, trong khi Firestore cung cấp các hoạt động hàng loạt một cách nguyên tử.

Hiệu suất và khả năng mở rộng

Cơ sở dữ liệu thời gian thực, như bạn mong đợi, khá mạnh mẽ và có độ trễ thấp. Tuy nhiên, cơ sở dữ liệu bị giới hạn ở các khu vực đơn lẻ, tùy thuộc vào tính khả dụng của khu vực. Mặt khác, Firestore lưu trữ dữ liệu theo chiều ngang trên nhiều vùng và khu vực để đảm bảo tính khả dụng, khả năng mở rộng và độ tin cậy thực sự trên toàn cầu. Trên thực tế, Google đã hứa rằng Firestore sẽ đáng tin cậy hơn Cơ sở dữ liệu thời gian thực.

Một thiếu sót khác của Cơ sở dữ liệu thời gian thực là giới hạn đối với 100.000 người dùng đồng thời (100.000 kết nối đồng thời và 1.000 lần ghi / giây trong một cơ sở dữ liệu duy nhất), sau đó bạn sẽ phải chia nhỏ cơ sở dữ liệu của mình (chia cơ sở dữ liệu của bạn thành nhiều cơ sở dữ liệu) để hỗ trợ nhiều người dùng hơn . Firestore tự động mở rộng quy mô trên nhiều trường hợp mà bạn không cần phải can thiệp.

Được thiết kế ngay từ đầu với khả năng mở rộng, Firestore có kiến ​​trúc giản đồ mới sao chép dữ liệu trên nhiều vùng, xử lý xác thực và xử lý các vấn đề liên quan đến bảo mật khác trong SDK phía máy khách của nó. Mô hình dữ liệu mới của nó trực quan hơn Firebase, gần giống với các giải pháp cơ sở dữ liệu NoSQL tương đương khác như MongoDB, đồng thời cung cấp một công cụ truy vấn mạnh mẽ hơn.

Bảo mật

Cuối cùng, Cơ sở dữ liệu thời gian thực, như bạn đã biết từ các hướng dẫn trước đây của chúng tôi, quản lý bảo mật thông qua các quy tắc xếp tầng với các trình kích hoạt xác thực riêng biệt. Điều này hoạt động với Quy tắc cơ sở dữ liệu Firebase, xác thực dữ liệu của bạn một cách riêng biệt. Mặt khác, Firestore cung cấp một mô hình bảo mật đơn giản hơn nhưng mạnh mẽ hơn, tận dụng các Quy tắc bảo mật của Cloud Firestore và Quản lý danh tính và truy cập (IAM), với việc tự động xác thực dữ liệu.

  • Phát triển thiết bị di động Quy tắc bảo mật cơ sở hạ tầngChike Mgbemena

Mô hình dữ liệu Firestore

Firestore là một cơ sở dữ liệu dựa trên tài liệu NoSQL, bao gồm các bộ sưu tập tài liệu, mỗi bộ sưu tập chứa dữ liệu. Vì là cơ sở dữ liệu NoSQL nên bạn sẽ không nhận được các bảng, hàng và các phần tử khác mà bạn sẽ tìm thấy trong cơ sở dữ liệu quan hệ, mà thay vào đó là các tập hợp các cặp khóa / giá trị mà bạn sẽ tìm thấy trong tài liệu.

Bạn hoàn toàn tạo tài liệu và bộ sưu tập bằng cách gán dữ liệu cho một tài liệu và nếu tài liệu hoặc bộ sưu tập không tồn tại, nó sẽ tự động được tạo cho bạn, vì bộ sưu tập luôn phải là nút gốc (đầu tiên). Đây là một lược đồ ví dụ về Nhiệm vụ đơn giản của dự án mà bạn sẽ làm việc trong thời gian ngắn, bao gồm bộ sưu tập Nhiệm vụ, cũng như nhiều tài liệu có chứa hai trường, tên (chuỗi) và cờ cho biết nhiệm vụ có được hoàn thành hay không (boolean) .

Hãy phân tích từng yếu tố để bạn có thể hiểu rõ hơn về chúng.

Bộ sưu tập

Đồng nghĩa với các bảng cơ sở dữ liệu trong thế giới SQL, các bộ sưu tập chứa một hoặc nhiều tài liệu. Bộ sưu tập phải là phần tử gốc trong lược đồ của bạn và chỉ có thể chứa tài liệu chứ không phải các bộ sưu tập khác. Tuy nhiên, bạn có thể tham chiếu đến một tài liệu đề cập đến các bộ sưu tập (tập hợp con).

Trong sơ đồ trên, một nhiệm vụ bao gồm hai trường nguyên thủy (tên và hoàn thành) cũng như một tập hợp con (nhiệm vụ con) bao gồm hai trường nguyên thủy của chính nó.

Tài liệu

Tài liệu bao gồm các cặp khóa / giá trị, với các giá trị có một trong các loại sau:

  • trường nguyên thủy (chẳng hạn như chuỗi, số, boolean)
  • các đối tượng lồng nhau phức tạp (danh sách hoặc mảng nguyên thủy)
  • tập hợp con

Các đối tượng lồng nhau còn được gọi là bản đồ và có thể được biểu diễn như sau, trong tài liệu. Sau đây là một ví dụ về một đối tượng và mảng lồng nhau, tương ứng:

ID: 2422892 //primitive
name: “Remember to buy milk” 
detail: //nested object
    notes: "This is a task to buy milk from the store"
	created: 2017-04-09
	due: 2017-04-10
done: false
notify: ["2F22-89R2", "L092-G623", "H00V-T4S1"]
...

Để biết thêm thông tin về các loại dữ liệu được hỗ trợ, hãy tham khảo tài liệu Loại dữ liệu của Google. Tiếp theo, bạn sẽ thiết lập một dự án để làm việc với Cloud Firestore.

Thiết lập dự án

Nếu bạn đã làm việc với Firebase trước đây, bạn sẽ thấy rất nhiều điều này. Nếu không, bạn sẽ cần tạo tài khoản trong Firebase và làm theo hướng dẫn trong phần 'Thiết lập dự án' của hướng dẫn trước đây của chúng tôi, Bắt đầu với Xác thực Firebase cho iOS.

Để làm theo hướng dẫn này, hãy sao chép repo dự án hướng dẫn. Tiếp theo, bao gồm thư viện Firestore của thêm phần sau vào Podfile của bạn :

pod 'Firebase/Core' 
pod 'Firebase/Firestore'

Nhập thông tin sau vào thiết bị đầu cuối của bạn để xây dựng thư viện của bạn:

pod install

Tiếp theo, chuyển sang Xcode và mở .xcworkspace tập tin. Điều hướng đến AppDelegate.swift và nhập thông tin sau vào ứng dụng application:didFinishLaunchingWithOptions: phương pháp:

FirebaseApp.configure()

Trong trình duyệt của bạn, đi tới bảng điều khiển Firebase và chọn Cơ sở dữ liệu tab ở bên trái.

Đảm bảo rằng bạn chọn tùy chọn Bắt đầu ở Chế độ kiểm tra để bạn không gặp bất kỳ vấn đề bảo mật nào trong khi chúng tôi thử nghiệm và chú ý đến thông báo bảo mật khi bạn chuyển ứng dụng của mình vào sản xuất. Bây giờ bạn đã sẵn sàng để tạo một bộ sưu tập và một số tài liệu mẫu.

Thêm Bộ sưu tập và Tài liệu Mẫu

Để bắt đầu, hãy tạo một bộ sưu tập ban đầu, Tasks , bằng cách chọn Thêm bộ sưu tập và đặt tên cho bộ sưu tập, như minh họa bên dưới:

Đối với tài liệu đầu tiên, bạn sẽ để trống ID tài liệu, ID này sẽ tự động tạo ID cho bạn. Tài liệu sẽ chỉ bao gồm hai trường:namedone .

Lưu tài liệu và bạn sẽ có thể xác nhận bộ sưu tập và tài liệu cùng với ID được tạo tự động:

Với cơ sở dữ liệu được thiết lập bằng tài liệu mẫu trên đám mây, bạn đã sẵn sàng để bắt đầu triển khai Firestore SDK trong Xcode.

Tạo &Làm việc với Tham chiếu Cơ sở dữ liệu

Mở MasterViewController.swift tệp trong Xcode và thêm các dòng sau để nhập thư viện:

import Firebase

class MasterViewController: UITableViewController {
    @IBOutlet weak var addButton: UIBarButtonItem!
    
    private var documents: [DocumentSnapshot] = []
    public var tasks: [Task] = []
    private var listener : ListenerRegistration!
   ...

Ở đây bạn chỉ cần tạo một biến trình lắng nghe sẽ cho phép bạn kích hoạt kết nối với cơ sở dữ liệu trong thời gian thực khi có thay đổi. Bạn cũng đang tạo một DocumentSnapshot tham chiếu sẽ giữ ảnh chụp nhanh dữ liệu tạm thời.

Trước khi tiếp tục với bộ điều khiển chế độ xem, hãy tạo một tệp nhanh khác, Task.swift , sẽ đại diện cho mô hình dữ liệu của bạn:

import Foundation

struct Task{
    var name:String
    var done: Bool
    var id: String
    
    var dictionary: [String: Any] {
        return [
            "name": name,
            "done": done
        ]
    }
}

extension Task{
    init?(dictionary: [String : Any], id: String) {
        guard   let name = dictionary["name"] as? String,
            let done = dictionary["done"] as? Bool
            else { return nil }
        
        self.init(name: name, done: done, id: id)
    }
}

Đoạn mã ở trên bao gồm thuộc tính tiện lợi (từ điển) và phương thức (init) sẽ giúp việc điền đối tượng mô hình dễ dàng hơn. Chuyển trở lại bộ điều khiển chế độ xem và khai báo một biến setter toàn cục sẽ giới hạn truy vấn cơ sở vào 50 mục hàng đầu trong danh sách nhiệm vụ. Bạn cũng sẽ xóa trình nghe khi bạn đặt biến truy vấn, như được biểu thị trong didSet thuộc tính bên dưới:

fileprivate func baseQuery() -> Query {
        return Firestore.firestore().collection("Tasks").limit(to: 50)
    }
    
    fileprivate var query: Query? {
        didSet {
            if let listener = listener {
                listener.remove()
            }
        }
    }

override func viewDidLoad() {
        super.viewDidLoad()
        self.query = baseQuery()
    }

 override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        self.listener.remove()
    }

Đọc dữ liệu trong thời gian thực từ Cloud Firestore

Với tài liệu tham khảo tại chỗ, trong viewWillAppear(_animated: Bool) , liên kết trình nghe bạn đã tạo trước đó với kết quả của ảnh chụp nhanh truy vấn và truy xuất danh sách tài liệu. Điều này được thực hiện bằng cách gọi phương thức Firestore query?.addSnapshotListener :

self.listener =  query?.addSnapshotListener { (documents, error) in
            guard let snapshot = documents else {
                print("Error fetching documents results: \(error!)")
                return
            }
            
            let results = snapshot.documents.map { (document) -> Task in
                if let task = Task(dictionary: document.data(), id: document.documentID) {
                    return task
                } else {
                    fatalError("Unable to initialize type \(Task.self) with dictionary \(document.data())")
                }
            }
            
            self.tasks = results
            self.documents = snapshot.documents
            self.tableView.reloadData()
            
        }

Việc đóng ở trên chỉ định snapshot.documents bằng cách ánh xạ lặp đi lặp lại mảng và gói nó vào một Task mới đối tượng cá thể mô hình cho từng mục dữ liệu trong ảnh chụp nhanh. Vì vậy, chỉ với một vài dòng, bạn đã đọc thành công tất cả các tác vụ từ đám mây và gán chúng cho các tác vụ tasks chung mảng.

Để hiển thị kết quả, hãy điền vào mục sau TableView phương pháp ủy quyền:

override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return tasks.count
    }
    
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        
        let item = tasks[indexPath.row]
        
        cell.textLabel!.text = item.name
        cell.textLabel!.textColor = item.done == false ? UIColor.black : UIColor.lightGray
        
        return cell
    }

Ở giai đoạn này, hãy xây dựng và chạy dự án và trong Trình mô phỏng, bạn sẽ có thể quan sát dữ liệu xuất hiện trong thời gian thực. Thêm dữ liệu qua bảng điều khiển Firebase và bạn sẽ thấy dữ liệu đó xuất hiện ngay lập tức trong trình mô phỏng ứng dụng.

Tạo, cập nhật và xóa dữ liệu

Sau khi đọc thành công nội dung từ back-end, tiếp theo bạn sẽ tạo, cập nhật và xóa dữ liệu. Ví dụ tiếp theo sẽ minh họa cách cập nhật dữ liệu, sử dụng một ví dụ có sẵn trong đó ứng dụng sẽ chỉ cho phép bạn đánh dấu một mục là đã xong bằng cách nhấn vào ô. Lưu ý collection.document( item.id ).updateData(["done": !item.done]) thuộc tính đóng, chỉ tham chiếu đến một ID tài liệu cụ thể, cập nhật từng trường trong từ điển:

override func tableView(_ tableView: UITableView,
                            didSelectRowAt indexPath: IndexPath) {

        let item = tasks[indexPath.row]
        let collection = Firestore.firestore().collection("Tasks")

        collection.document(item.id).updateData([
            "done": !item.done,
            ]) { err in
                if let err = err {
                    print("Error updating document: \(err)")
                } else {
                    print("Document successfully updated")
                }
        }

        tableView.reloadRows(at: [indexPath], with: .automatic)
        
    }

Để xóa một mục, hãy gọi tài liệu document( item.id ).delete() phương pháp:

override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        return true
    }
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {

        if (editingStyle == .delete){
            let item = tasks[indexPath.row]
            _ = Firestore.firestore().collection("Tasks").document(item.id).delete()
        }

    }

Tạo một nhiệm vụ mới sẽ liên quan đến việc thêm một nút mới trong Bảng phân cảnh của bạn và kết nối IBAction của nó vào bộ điều khiển chế độ xem, tạo addTask(_ sender:) phương pháp. Khi người dùng nhấn nút, nó sẽ hiển thị một trang thông báo nơi người dùng có thể thêm tên tác vụ mới:

collection("Tasks").addDocument
    (data: ["name": textFieldReminder.text ?? 
        "empty task", "done": false])

Hoàn thành phần cuối cùng của ứng dụng bằng cách nhập thông tin sau:

@IBAction func addTask(_ sender: Any) {
        
        let alertVC : UIAlertController = UIAlertController(title: "New Task", message: "What do you want to remember?", preferredStyle: .alert)
        
        alertVC.addTextField { (UITextField) in
            
        }
        
        let cancelAction = UIAlertAction.init(title: "Cancel", style: .destructive, handler: nil)
        
        alertVC.addAction(cancelAction)
        
        //Alert action closure
        let addAction = UIAlertAction.init(title: "Add", style: .default) { (UIAlertAction) -> Void in
            
            let textFieldReminder = (alertVC.textFields?.first)! as UITextField
            
            let db = Firestore.firestore()
            var docRef: DocumentReference? = nil
            docRef = db.collection("Tasks").addDocument(data: [
                "name": textFieldReminder.text ?? "empty task",
                "done": false
            ]) { err in
                if let err = err {
                    print("Error adding document: \(err)")
                } else {
                    print("Document added with ID: \(docRef!.documentID)")
                }
            }
            
        }
    
        alertVC.addAction(addAction)
        present(alertVC, animated: true, completion: nil)
        
    }

Xây dựng và chạy ứng dụng một lần nữa và khi trình mô phỏng xuất hiện, hãy thử thêm một số tác vụ, cũng như đánh dấu một số tác vụ là xong và cuối cùng kiểm tra chức năng xóa bằng cách xóa một số tác vụ. Bạn có thể xác nhận rằng dữ liệu được lưu trữ đã được cập nhật trong thời gian thực bằng cách chuyển sang bảng điều khiển cơ sở dữ liệu Firebase của bạn và quan sát bộ sưu tập và tài liệu.

Truy vấn lọc và kết hợp

Cho đến nay, bạn chỉ làm việc với một truy vấn đơn giản mà không có bất kỳ khả năng lọc cụ thể nào. Để tạo các truy vấn mạnh mẽ hơn một chút, bạn có thể lọc theo các giá trị cụ thể bằng cách sử dụng whereField mệnh đề:

docRef.whereField(“name”, isEqualTo: searchString)

Bạn có thể sắp xếp và giới hạn dữ liệu truy vấn của mình bằng cách sử dụng order(by: )limit(to: ) như sau:

docRef.order(by: "name").limit(5)

Trong ứng dụng FirebaseDo, bạn đã sử dụng limit với truy vấn cơ sở. Trong đoạn mã trên, bạn cũng đã sử dụng một tính năng khác, truy vấn ghép, trong đó cả thứ tự và giới hạn đều được xâu chuỗi với nhau. Bạn có thể xâu chuỗi bao nhiêu truy vấn tùy thích, chẳng hạn như trong ví dụ sau:

docRef
    .whereField(“name”, isEqualTo: searchString)
	.whereField(“done”, isEqualTo: false)
	.order(by: "name")
	.limit(5)

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Sử dụng AT TIME ZONE để sửa một báo cáo cũ

  2. Cách trở thành nhà thiết kế cơ sở dữ liệu

  3. Mô hình dữ liệu

  4. Tạo số nguyên ngẫu nhiên mà không có xung đột

  5. Kiểu dữ liệu SQL VARCHAR Nên và Không nên để Cơ sở dữ liệu Nhanh hơn