Google cam kết thúc đẩy công bằng chủng tộc cho Cộng đồng người da đen. Xem cách thực hiện.
Trang này được dịch bởi Cloud Translation API.
Switch to English

Cấu trúc cơ sở dữ liệu của bạn

Trước khi bắt đầu

Trước khi có thể sử dụng Cơ sở dữ liệu thời gian thực , bạn cần:

  • Đăng ký dự án Unity của bạn và định cấu hình nó để sử dụng Firebase.

    • Nếu dự án Unity của bạn đã sử dụng Firebase thì dự án đó đã được đăng ký và định cấu hình cho Firebase.

    • Nếu bạn không có dự án Unity, bạn có thể tải xuống một ứng dụng mẫu .

  • Thêm SDK Unity Firebase (cụ thể là FirebaseDatabase.unitypackage ) vào dự án Unity của bạn.

Lưu ý rằng việc thêm Firebase vào dự án Unity của bạn liên quan đến các tác vụ trong bảng điều khiển Firebase và trong dự án Unity đang mở của bạn (ví dụ: bạn tải xuống tệp cấu hình Firebase từ bảng điều khiển, sau đó di chuyển chúng vào dự án Unity của bạn).

Cấu trúc dữ liệu

Hướng dẫn này bao gồm một số khái niệm chính trong kiến ​​trúc dữ liệu và các phương pháp hay nhất để cấu trúc dữ liệu JSON trong Cơ sở dữ liệu thời gian thực Firebase của bạn.

Việc xây dựng một cơ sở dữ liệu có cấu trúc thích hợp đòi hỏi khá nhiều suy nghĩ trước. Quan trọng nhất, bạn cần lập kế hoạch về cách dữ liệu sẽ được lưu và truy xuất sau này để làm cho quá trình đó trở nên dễ dàng nhất có thể.

Cách dữ liệu được cấu trúc: đó là một cây JSON

Tất cả dữ liệu Cơ sở dữ liệu thời gian thực của Firebase được lưu trữ dưới dạng các đối tượng JSON. Bạn có thể coi cơ sở dữ liệu như một cây JSON được lưu trữ trên đám mây. Không giống như cơ sở dữ liệu SQL, không có bảng hoặc bản ghi. Khi bạn thêm dữ liệu vào cây JSON, nó sẽ trở thành một nút trong cấu trúc JSON hiện có với một khóa được liên kết. Bạn có thể cung cấp các khóa của riêng mình, chẳng hạn như ID người dùng hoặc tên ngữ nghĩa hoặc chúng có thể được cung cấp cho bạn bằng cách sử dụng phương thức Push() .

Nếu bạn tạo khóa của riêng mình, chúng phải được mã hóa UTF-8, có thể có kích thước tối đa là 768 byte và không được chứa . Các ký tự điều khiển, $ , # , [ , ] , / hoặc ASCII 0-31 hoặc 127. Bạn cũng không thể sử dụng các ký tự điều khiển ASCII trong chính các giá trị.

Ví dụ: hãy xem xét một ứng dụng trò chuyện cho phép người dùng lưu trữ hồ sơ cơ bản và danh sách liên hệ. Một hồ sơ người dùng điển hình được đặt tại một đường dẫn, chẳng hạn như /users/$uid . Người dùng alovelace có thể có một mục nhập cơ sở dữ liệu trông giống như sau:

{
  "users": {
    "alovelace": {
      "name": "Ada Lovelace",
      "contacts": { "ghopper": true },
    },
    "ghopper": { ... },
    "eclarke": { ... }
  }
}

Mặc dù cơ sở dữ liệu sử dụng cây JSON, dữ liệu được lưu trữ trong cơ sở dữ liệu có thể được biểu diễn dưới dạng một số kiểu gốc nhất định tương ứng với các kiểu JSON có sẵn để giúp bạn viết mã dễ bảo trì hơn.

Các phương pháp hay nhất cho cấu trúc dữ liệu

Tránh lồng ghép dữ liệu

Vì Cơ sở dữ liệu thời gian thực của Firebase cho phép lồng dữ liệu sâu tới 32 cấp, bạn có thể bị cám dỗ khi nghĩ rằng đây phải là cấu trúc mặc định. Tuy nhiên, khi bạn tìm nạp dữ liệu tại một vị trí trong cơ sở dữ liệu của mình, bạn cũng truy xuất tất cả các nút con của nó. Ngoài ra, khi bạn cấp cho ai đó quyền truy cập đọc hoặc ghi tại một nút trong cơ sở dữ liệu của mình, bạn cũng cấp cho họ quyền truy cập vào tất cả dữ liệu trong nút đó. Do đó, trong thực tế, tốt nhất là giữ cho cấu trúc dữ liệu của bạn càng phẳng càng tốt.

Để biết ví dụ về lý do tại sao dữ liệu lồng nhau là xấu, hãy xem xét cấu trúc lồng ghép nhiều nhân sau:

{
  // This is a poorly nested data architecture, because iterating the children
  // of the "chats" node to get a list of conversation titles requires
  // potentially downloading hundreds of megabytes of messages
  "chats": {
    "one": {
      "title": "Historical Tech Pioneers",
      "messages": {
        "m1": { "sender": "ghopper", "message": "Relay malfunction found. Cause: moth." },
        "m2": { ... },
        // a very long list of messages
      }
    },
    "two": { ... }
  }
}

Với thiết kế lồng nhau này, việc lặp lại dữ liệu trở nên có vấn đề. Ví dụ: liệt kê tiêu đề của các cuộc trò chuyện yêu cầu toàn bộ cây chats , bao gồm tất cả các thành viên và tin nhắn, phải được tải xuống ứng dụng khách.

Làm phẳng cấu trúc dữ liệu

Thay vào đó, nếu dữ liệu được chia thành các đường dẫn riêng biệt, còn được gọi là không chuẩn hóa, nó có thể được tải xuống một cách hiệu quả trong các lệnh gọi riêng biệt, khi cần thiết. Hãy xem xét cấu trúc phẳng này:

{
  // Chats contains only meta info about each conversation
  // stored under the chats's unique ID
  "chats": {
    "one": {
      "title": "Historical Tech Pioneers",
      "lastMessage": "ghopper: Relay malfunction found. Cause: moth.",
      "timestamp": 1459361875666
    },
    "two": { ... },
    "three": { ... }
  },

  // Conversation members are easily accessible
  // and stored by chat conversation ID
  "members": {
    // we'll talk about indices like this below
    "one": {
      "ghopper": true,
      "alovelace": true,
      "eclarke": true
    },
    "two": { ... },
    "three": { ... }
  },

  // Messages are separate from data we may want to iterate quickly
  // but still easily paginated and queried, and organized by chat
  // conversation ID
  "messages": {
    "one": {
      "m1": {
        "name": "eclarke",
        "message": "The relay seems to be malfunctioning.",
        "timestamp": 1459361875337
      },
      "m2": { ... },
      "m3": { ... }
    },
    "two": { ... },
    "three": { ... }
  }
}

Giờ đây, bạn có thể lặp lại danh sách các phòng bằng cách tải xuống chỉ vài byte cho mỗi cuộc hội thoại, nhanh chóng tìm nạp siêu dữ liệu để liệt kê hoặc hiển thị các phòng trong giao diện người dùng. Tin nhắn có thể được tìm nạp riêng và hiển thị khi chúng đến, cho phép giao diện người dùng luôn phản hồi nhanh chóng.

Tạo dữ liệu có quy mô

Khi xây dựng ứng dụng, thường tốt hơn là tải xuống một tập hợp con của danh sách. Điều này đặc biệt phổ biến nếu danh sách chứa hàng nghìn bản ghi. Khi mối quan hệ này là tĩnh và một chiều, bạn có thể chỉ cần lồng các đối tượng con dưới đối tượng cha.

Đôi khi, mối quan hệ này năng động hơn hoặc có thể cần phải chuẩn hóa dữ liệu này. Nhiều khi bạn có thể không chuẩn hóa dữ liệu bằng cách sử dụng truy vấn để truy xuất một tập hợp con của dữ liệu, như đã thảo luận trong Truy xuất dữ liệu .

Nhưng ngay cả điều này có thể là không đủ. Ví dụ, hãy xem xét mối quan hệ hai chiều giữa người dùng và nhóm. Người dùng có thể thuộc về một nhóm và các nhóm bao gồm danh sách người dùng. Khi đến lúc quyết định người dùng thuộc nhóm nào, mọi thứ trở nên phức tạp.

Điều cần thiết là một cách thanh lịch để liệt kê các nhóm mà người dùng thuộc về và chỉ tìm nạp dữ liệu cho các nhóm đó. Chỉ mục của các nhóm có thể giúp ích rất nhiều ở đây:

// An index to track Ada's memberships
{
  "users": {
    "alovelace": {
      "name": "Ada Lovelace",
      // Index Ada's groups in her profile
      "groups": {
         // the value here doesn't matter, just that the key exists
         "techpioneers": true,
         "womentechmakers": true
      }
    },
    ...
  },
  "groups": {
    "techpioneers": {
      "name": "Historical Tech Pioneers",
      "members": {
        "alovelace": true,
        "ghopper": true,
        "eclarke": true
      }
    },
    ...
  }
}

Bạn có thể nhận thấy rằng điều này sao chép một số dữ liệu bằng cách lưu trữ mối quan hệ dưới cả bản ghi của Ada và trong nhóm. Giờ đây, alovelace được lập chỉ mục trong một nhóm và các nhà công techpioneers được liệt kê trong hồ sơ của Ada. Vì vậy, để xóa Ada khỏi nhóm, nó phải được cập nhật ở hai nơi.

Đây là sự dư thừa cần thiết cho mối quan hệ hai chiều. Nó cho phép bạn nhanh chóng và hiệu quả tìm nạp tư cách thành viên của Ada, ngay cả khi danh sách người dùng hoặc nhóm có quy mô hàng triệu hoặc khi các quy tắc bảo mật Cơ sở dữ liệu thời gian thực ngăn quyền truy cập vào một số bản ghi.

Cách tiếp cận này, đảo ngược dữ liệu bằng cách liệt kê các ID dưới dạng khóa và đặt giá trị thành true, giúp việc kiểm tra khóa đơn giản như đọc /users/$uid/groups/$group_id và kiểm tra xem nó có null . Chỉ mục nhanh hơn và hiệu quả hơn rất nhiều so với việc truy vấn hoặc quét dữ liệu.

Bước tiếp theo