Firestore: Как запросить объект карты внутри коллекции документов? - PullRequest
0 голосов
/ 21 февраля 2019

Моя цель:

Веб-приложение (похожее на Google Drive) имеет 2 экрана.

Первый экран - «Моя история», в котором отображаются все документы истории, владельцем которых я являюсь.

Второй экран - «Делится со мной», в котором отображаются все документы истории, которыми я являюсьчитатель, писатель или комментатор.

У нас есть / Stories / {storyid}

{
  title: "A Great Story",
  content: "Once upon a time ...",
  roles: {
    alice: "owner",
    bob: "reader",
    david: "writer",
    jane: "commenter"
    // ...
  }
}

Полная ссылка на структуру данных: https://firebase.google.com/docs/firestore/solutions/role-based-access

Вопрос: Как написать приведенный ниже запрос для выполнения вышеуказанной цели?

db
.collection('stories')
.where(`roles.${uid}`, '==', 'owner')

Вышеприведенный запрос НЕ работает, так как он потребует Firestore для индексирования role.alice, role.bob, role.david, role.jane и ролей. [all_uid].


Редактировать # 1: Нашел связанный пост (без ответов), спрашивающий о Запросы Firestore с ролями

Ответы [ 2 ]

0 голосов
/ 21 февраля 2019

Это невозможно, поэтому нам необходимо дублировать данные в NoSQL.

Одна из возможных структур данных:

/ Stories / {storyid}

{
  title: "A Great Story",
  content: "Once upon a time ...",
  roles: {
    alice: "owner",
    bob: "reader",
    david: "writer",
    jane: "commenter",
    mary: "writer",
    // ...
  },
  owner: "alice", // newly added
  shared: ["bob", "david", "jane", "mary"] // newly added
  // alice, bob, david, jane, mary are firebase auth uid
}

Таким образом, мы можем запросить пользовательский интерфейс веб-приложения «Моя история»

db
.collection('stories')
.where('owner', '==', uid)

В то время как мы можем запросить пользовательский интерфейс веб-приложения «Shared with me»

db
.collection('stories')
.where('shared', 'array_contains', uid)

Ответ вдохновлен комментариями @Doug Stevenson.

0 голосов
/ 21 февраля 2019

Вы не можете достичь этого с вашей реальной структурой базы данных таким образом, что вам не нужно создавать индекс для каждого пользователя в отдельности.Чтобы справиться с этим, вы должны продублировать свои данные.Эта практика называется denormalization и является обычной практикой, когда дело доходит до Firebase.Если вы новичок в базах данных NoQSL, я рекомендую вам посмотреть это видео, Денормализация нормальна с базой данных Firebase для лучшего понимания.Это для базы данных реального времени Firebase, но те же правила применяются к Cloud Firestore.

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

При этом вам следует создать еще одну коллекцию с именем userStories, куда вы должны добавитьв качестве документов все истории, где пользователь owner.Таким образом, ваша структура базы данных должна выглядеть примерно так:

Firestore-root
   |
   --- userStories (collection)
         |
         --- uid (document)
              |
              --- allStories (collection)
                     |
                     --- storyId
                           |
                           --- role: "owner"

Итак, запрос вроде этого:

db.collection('userStories').doc(${uid})
    .collection('allStories').where(`role`, '==', 'owner');

будет отлично работать.

...