Структурирование данных для приложения чата в Firebase

Следующее руководство Firebase по структурирование данных для чата. Они предлагают структуру, как показано ниже.

{
  // Chats contains only meta info about each conversation
  // stored under the chats 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
  // converation ID
  "messages": {
    "one": {
      "m1": {
        "name": "eclarke",
        "message": "The relay seems to be malfunctioning.",
        "timestamp": 1459361875337
      },
      "m2": { ... },
      "m3": { ... }
    },
    "two": { ... },
    "three": { ... }
  }
}

Как структурировать свои пользовательские данные, чтобы я мог легко отображать список всех чатов, в которых они являются, и для каждого из них отображает последнее сообщение и временную метку. Если я сделаю следующую структуру:

   "users": {
    "ghopper": {
      "name": "Gary Hopper",
      "chats": {
          "one: true",
          "two": true
      }
    },
    "alovelace" { ... }
  },

Я могу легко получить список каждой группы чатов для конкретного пользователя, например, ghopper, выполнив (в быстрой):

ref.child("users").child("ghopper").child("chats").observeSingleEventOfType(.Value, withBlock: { (snapshot) in
  //do something with data
}

Однако в этом снимке я не буду иметь lastMessage и timestamp. Что мне нужно сделать для доступа к этим данным?

  • Дублировать все эти данные для каждого пользователя? добавив пользователей /ghopper/chats/one/ { "lastMessage": "ghopper: обнаружена неисправность реле. Причина: moth.", "timestamp": 1459361875666}
  • Сделать запрос для "chats/specificGroupId" для каждого чата, частью которого является пользователь (добавление нескольких списков)?
  • Другой способ?

Ответ 1

Как структурировать свои пользовательские данные, чтобы я мог легко отобразить список все чаты, в которых они входят, и для каждого из них отображаются последнее сообщение и временную метку.

Измените структуру чатов, добавив пользователей, которые находятся в чате node

"chats": {
    "one": {
      "title": "Historical Tech Pioneers",
      "lastMessage": "ghopper: Relay malfunction found. Cause: moth.",
      "timestamp": 1459361875666
      users
       uid_1: true
       uid_3: true
    },
    "two": { ... },

Затем вы можете выполнить глубокий запрос для всех чатов, к которым относится определенный пользователь - это вернет чаты, которые uid_3 участвует в

chatsRef.queryOrderedByChild("users/uid_3").queryEqualToValue(true)
     .observeSingleEventOfType(.Value, withBlock: { snapshot in

     //.Value can return multiple nodes within the snapshot so iterate over them
     for child in snapshot.children {
          let lastmsg = child.value["lastMessage"] as! String
          let timestamp = child.value["timestamp"] as! String
          print(lastmsg)
          print(timestamp)
     }     
})

Обратите внимание, что каждый пользователь firebase имеет скрытый идентификатор пользователя, полученный при создании пользователя через auth.uid. Это должно (как правило) использоваться как ключ для каждого пользователя.

Ответ 2

В блоке, где у вас есть список всех чатов, в которых находится пользователь, вы можете:

var dictionary: [String: Long]   
var lastMessage: String 
for chat in listOfChatsUserIsIn
    ref.child("chats").child("\(chat)").child("lastMessage").observeSingleEventOfType(.Value, withBlock: { (snapshot) in
        lastMessage = snapshot
        ref.child("chats").child("\(chat)").child("timestamp").observeSingleEventOfType(.Value, withBlock: { (snapshot) in
            //add timestamp and last message to dictionary
        }
    }

Я не знаю, насколько корректен мой синтаксис. Все еще изучая огненную базу. Но, я думаю, это в основном ваше второе предложение. Не знаю, как еще вы получите данные. Это будет O (2n), хотя это неплохо.

[[Обновить 1]]

Я лгал своим кодом. Я помещаю lastMessage = моментальный снимок, чтобы сохранить его, чтобы вы могли добавить его в словарь в следующем блоке.

Что касается Firebase, являющегося асинхронным. Я думаю, что это все равно будет работать, пока вы используете либо метку времени, либо сообщение как ключ, а другое как значение в словаре. Он может быть заполнен не по порядку, но вы всегда можете отсортировать его по метке времени позже. Хотя, да, это, вероятно, не самая лучшая практика.

Джей, мне нравится ваше решение. Вам не нужно было бы также перечислить uid_2: false?

К сожалению, кажется, что обе эти структуры базы данных растут на n ^ 2 как пользователи → inf и как чаты → inf.