AngularFire2 с Firebase Realtime DB - Вложенные запросы данных Angular 6 [duplicate]

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

a.active h1 {color:red;}

a.active:hover h1 {color:green;}

a.active h2 {color:blue;}

a.active:hover h1 {color:yellow;}

Таким образом вы можете изменить стиль во множестве внутренних тегов на основе опрокидывания родительского элемента.

33
задан Frank van Puffelen 17 November 2016 в 15:11
поделиться

1 ответ

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

Несколько проблем здесь:

  • вы сохраняете set в качестве массива
  • вы можете индексировать только по фиксированным путям

Установить vs array

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

participants: ["puf", "puf"]

Это явно не то, что вы имеете в виду, но структура данных позволяет это. Вы можете попытаться обеспечить это в коде и правилах безопасности, но было бы проще, если бы вы начали с структуры данных, которая неявно соответствует вашей модели.

Мое эмпирическое правило: если вы обнаружите, что пишете array.contains(), вы должны использовать набор.

Набор представляет собой структуру, в которой каждый ребенок может присутствовать не более одного раза, поэтому он естественным образом защищает от дубликатов. В Firebase вы моделируете набор как:

participants: {
  "puf": true
}

Здесь true здесь действительно просто фиктивное значение: важно то, что мы переместили имя на ключ. Теперь, если я попытаюсь снова присоединиться к чату, это будет noop:

participants: {
  "puf": true
}

И когда вы присоединитесь:

participants: {
  "john": true,
  "puf": true
}

Это самый прямой представление вашего требования: коллекция, которая может содержать только каждого участника один раз.

Вы можете индексировать только фиксированные пути

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

ref.child("chats").orderByChild("participants/john").equalTo(true)

Проблема заключается в том, что для этого требуется, чтобы вы определяли индекс для `members / john ':

{
  "rules": {
    "chats": {
      "$chatid": {
        "participants": {
          ".indexOn": ["john", "puf"]
        }
      }
    }
  }
}

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

Инвертировать индексы - тянуть категории вверх, сглаживание дерева

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

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

userChatrooms: {
  john: {
    chatRoom1: true,
    chatRoom2: true
  },
  puf: {
    chatRoom1: true,
    chatRoom3: true
  }
}

Теперь вы можете si просто определите свой список чатов с помощью:

ref.child("userChatrooms").child("john")

И затем перейдите по клавишам, чтобы получить каждую комнату.

Вам понравится иметь два соответствующих списка в вашем приложении:

  • список чатов для конкретного пользователя
  • список участников в определенной комнате чата

Кроме того, в базе данных есть оба списка.

chatroomUsers
  chatroom1
    user1: true
    user2: true
  chatroom2
    user1: true
    user3: true
userChatrooms
  user1:
    chatroom1: true
    chatroom2: true
  user2:
    chatroom1: true
  user2:
    chatroom2: true

Я вытащил оба списка на верхний уровень дерева, так как Firebase рекомендует против вложенных данных.

Наличие обоих списков совершенно нормально в решениях NoSQL. В приведенном выше примере мы будем ссылаться на userChatrooms как инвертированный индекс chatroomsUsers.

51
ответ дан Frank van Puffelen 18 August 2018 в 18:52
поделиться
  • 1
    Это удивительное объяснение. У меня есть данные, хранящиеся таким образом, что позволяет мне захватывать чат из списка пользователей или захватывать пользователя из членов чата. Но это не позволяет наблюдать .childChanged за чаты, членом которых я являюсь. Если я попытаюсь настроить наблюдателя для чатов, где members/myId = true, то я получаю неуказанную ошибку индекса. Как бы вы это сделали? У меня есть вопрос, размещенный здесь: stackoverflow.com/questions/47769044/… – lusus_vir 17 December 2017 в 00:14
  • 2
    @ frank-van-puffelen, ссылаясь на ваш последний фрагмент кода, допустим, я «user1». и я забираю все ключи чатов, в которых я состою. Затем для каждого ключевого слова в чате я получаю полный объект в чате и показываю список чатов в списке. Это хорошо, однако, что, если мне также понадобится доступ к объектам полного пользователя, которые являются частью чата. Кажется очень странным, что мне нужно будет сделать еще один цикл for (loop-loop) (2-уровневый вложенный for-loop!) Для каждого отдельного пользователя в каждом отдельном чате, чтобы получить эти данные. Есть ли способ лучше? – damirstuhec 6 February 2018 в 12:34
  • 3
    он решил мою аналогичную проблему, спасибо – Sitecore Sam 20 June 2018 в 09:25
Другие вопросы по тегам:

Похожие вопросы: