Запрос ключа объекта в Firestore - PullRequest
3 голосов
/ 29 марта 2020

У меня в настоящее время есть несколько проблем с моей техникой запросов Firestore. Согласно этому сообщению, которое я недавно сделал в стеке, Запрос с двумя массивами с правилами безопасности firestore

В ответе предлагается добавить «id» в объект с ключом в качестве id, и значение просто «истинно». Я завершил это, и теперь моя структура выглядит так:

enter image description here

Это оставляет меня с этим запросом:

db.collection('Depots')
  .where(`products.${productId}`, '==', true)
  .where(`users.${userId}`, '==', true)
  .where('created', '>', 1585998560500)
  .orderBy('created', 'asc')
  .get();

Этот запрос оставляет мне сообщение об ошибке с запросом на создание индекса:

Для запроса требуется индекс. Вы можете создать его здесь: ...

Однако, он пытается проиндексировать указанный ключ объекта c, то есть QXooVYGBIFWKo6C, поэтому products.QXooVYGBIFWKo6C. Что, конечно, не то, что я хочу, так как этот запрос изменяется, и может иметь бесконечное количество возможностей, что означает, что мне придется создать другой индекс для каждой ключевой записи, чтобы запросить его.

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

Заранее большое спасибо.

Ответы [ 3 ]

4 голосов
/ 29 марта 2020

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

Это действительно означает, что у вас будет столько индексов, сколько у вас продуктов, что означает:

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

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

1 голос
/ 29 марта 2020

После нашего обсуждения в чате, это отправная точка, которую я бы предложил. Кто знает, как будет выглядеть конечная архитектура, но я думаю, что это или очень близко к этому. Вы говорите, что пользователь может существовать в нескольких хранилищах одновременно, и несколько хранилищ могут содержать одни и те же продукты, в то же время. Вы также сказали, что в хранилище никогда не может быть более 40 пользователей одновременно, поэтому массив из 40 пользователей, безусловно, не будет вторгаться в лимит документов Firestore в 1,048,576 байт.

[collection]
    <documentId>
        - field: value

[depots]

    <UUID>
        - depotId: string       "depot456"
        - productCount: num     5,000

    <UUID>
        - depotId: string       "depot789"
        - productCount: num     4,500


[products]

    <UUID>
        - productId: string     "lotion123"
        - depotId: string       "depot456"
        - users: [string]       ["user10", "user27", "user33"]

    <UUID>
        - productId: string     "lotion123"
        - depotId: string       "depot789"
        - users: [string]       ["user10", "user17", "user50"]


[users]

    <userId>
        - depots: [string]      ["depot456", "depot999"]

    <userId>
        - depots: [string]      ["depot333", "depot999"]

In No SQL, хранилище дешево и вычисления не настолько денормализуют ваши данные, сколько вам нужно, чтобы ваши запросы были возможными и эффективными (быстрыми и дешевыми).

Чтобы найти все хранилища в одном запросе, где user10 и lotion123 оба имеют значение true, запрашивают коллекцию продуктов, где productId равно x и users array-содержит y и собирают значения depotId из этих результатов. Если вы хотите сохранить операцию, содержащую массив, для чего-то другого, вам придется дополнительно денормализовать ваши данные (заменить массив для одного пользователя). Или вы можете разделить этот запрос на два отдельных запроса.

В этой модели, когда пользователь покидает депо, получите все продукты, в которых users массив содержит этого пользователя, и удалите этот userId из массива. А когда пользователь присоединяется к депо, возьмите все продукты, где depotId равно x, и добавьте userId к массиву.

Просмотрите это видео и другие материалы Рика, чтобы получить solid ручка на № SQL: https://www.youtube.com/watch?v=HaEPXoXVf2k

0 голосов
/ 29 марта 2020

@ danwillm Если вы не уверены в количестве пользователей и продуктов, то ваша структура БД кажется непригодной для этой ситуации, поскольку существуют ограничения по размеру и длине документа пожарного депо. Вам лучше создать отдельную коллекцию для продуктов и пользователей, т.е. нормализовать ваши данные и иметь ссылку для пользователя в коллекции продуктов.

User : 
       {
          userId: documentId,
          name: John,
          ...otherInfo
       }

Product : 

       {
          productId: documentId,
          createdBy: userId,
          createdOn:date,
          productName:"exa",
          ...otherInfo
       }

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...