Обработка большого количества данных в Firebase или как избежать ограничений "где" в "? - PullRequest
0 голосов
/ 18 марта 2020

Может кто-нибудь помочь мне с запросами агрегации в Firestore. Кажется, что Firestore это все об ограничениях и ограничениях.

У меня есть две коллекции, и мне нужно собрать определенное количество пользователей с помощью фильтрации .limit(), а затем мне нужно искать соответствующие записи в другой коллекции.

Второй запрос, который я делаю с фильтром where in, но, очевидно, у меня может быть только 10 элементов в массиве запросов в фильтре where in.

Единственным способом, которым мне удалось обработать этот запрос, является:

           async ({ query }: Request, res: Response) => {
                const users: any = [];
                const ids: any = [];
                const stats: any = [];

                await firestore.collection('users').limit(30).get()
                    .then((snapshot) => {
                        let i = 1;
                        let d: any = [];

                        snapshot.forEach(doc => {
                            users.push(doc.data());

                            if (i <= 9) {
                                d.push(doc.data().id);
                                i++;
                            } else if (i === 10) {
                                d.push(doc.data().id);
                                i = 1;
                                ids.push(d);
                                d = [];
                            }

                        });

                    }).catch(console.log);

                const promises: any = [];

                ids.forEach((tens: any, index: number) => {
                    if (tens) {
                        promises.push(firestore.collection('users_statistic').
                            where('user_id', 'in', ids[index])
                            .get()
                            .then((snapshot) => {
                                const data: any = [];

                                snapshot.forEach(doc => data.push(doc.data()))
                                return data;
                            }))
                    }
                });

                await Promise.all(promises).then(stat => {
                    stat.forEach(t => {
                        stats.push(...(t as []));
                    })
                }).catch(console.log);

                const sortedStats: any = {};
                users.forEach((user: any) => {
                    sortedStats[user.id] = stats.filter((data: any) => data.user_id === user.id);
                });

                const totals = [];

                for (const key in sortedStats) {
                    if (sortedStats.hasOwnProperty(key)) {
                        const value = sortedStats[key];

                        const clicks = value.reduce((acc: any, v: any) => acc + v.clicks, 0);
                        const views = value.reduce((acc: any, v: any) => acc + v.page_views, 0);

                        totals.push({
                            ...users[key],
                            clicks,
                            views
                        })
                    }
                }

                res.status(200).send(totals);

}

  1. Я беру список пользователей
  2. Беру их идентификаторы и создаю партии массивов, которые включите до десяти идентификаторов
  3. Составьте список запросов и назначьте один массив из десяти идентификаторов (очевидно, это не очень хорошая идея, и я хотел избежать этого. Я должен сделать много запросов к базе данных Firestore)
  4. К Promise.all Я выполняю все свои обещания
  5. Фильтрация и сортировка результатов при подготовке выходных данных

Буду признателен за любую помощь здесь

Заранее спасибо !

1 Ответ

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

Если вам нужно выполнить много агрегаций ad-ho c, то Firestore, вероятно, не лучшая база данных для вас. В такой ситуации вам, вероятно, лучше использовать базу данных, более подходящую для запросов ad-ho c, таких как, например, BigQuery, которая выделяется при таких запросах агрегации для произвольно больших наборов данных.

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

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

Эта topi c появлялась несколько раз, поэтому также смотрите:

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