Превышен предел памяти Firestore при получении нескольких документов из коллекции

Я пытаюсь получить все документы в коллекции Firestore, где мое поле referredBy равно переменной refCode (реферальный код). Я продолжаю получать ошибку в Stackdriver: «Ошибка: превышен предел памяти. Вызов функции был прерван».

Инструкции для этой функции находятся здесь: https://firebase.google.com/docs/firestore/query-data/get-data#get_multiple_documents_from_a_collection

Я попытался увеличить выделение памяти для этой облачной функции до 2 ГБ (макс.), Но все равно возникла та же ошибка. В этой коллекции только два документа и только один, который соответствует моим критериям «где», так что размер документов в любом случае не должен быть проблемой.

Это из моего index.js:

const express = require('express');
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const app = express();

// Get referred users:
app.get('path/to/myapp', (req, res) => {

    var getReferred = require('./getRefUsers');
    if (admin.apps.length === 0 ) { admin.initializeApp(functions.config().firebase); }
    var db = admin.firestore();
    getReferred.getUsersReferred(req, res, db);
});
exports.getReferred = functions.https.onRequest(app);

Что вызывает следующую функцию:

module.exports = {

getUsersReferred: function(req, res, db) {

    const { shopName, twitchId } = req.query;

    // Get users account to get their referral code:
    var docRef = db.collection('stores').doc(shopName).collection('users').doc(twitchId);
    docRef.get()
        .then((docSnapshot) => {                                                                    
            if (!docSnapshot.exists) {
                var msg = 'User ' + twitchId + ' does not exist.';
                console.info(msg);
                res.json({ 'status': 'error', 'message': msg });
            } else {

                var referredUsers = [];

                // Get all users who were referred by this user
                var refCode = docSnapshot.data().referralCode;
                console.info('refCode: ' + refCode + ' shop: ' + shopName + ' id: ' + twitchId);

                db.collection('stores').doc(shopName).collection('users').where("referredBy", "= = ", refCode)
                    .get()
                    .then(function(querySnapshot) {
                            console.info('Size: ' + querySnapshot.size);

                            querySnapshot.forEach(function(doc) {
                                // doc.data() is never undefined for query doc snapshots
                                console.info(doc.id, " => ", doc.data());
                                var username = doc.data().username;
                                var earned = doc.data().earnedreferpoints;
                                var id = doc.data().twitchId;
                                if (typeof earned == 'undefined' || earned == 'no') {
                                    earned = 'No';
                                } else {
                                    earned = 'Yes';
                                }

                                if (doc.data().referredBy == refCode) {
                                    referredUsers[id] = [username, earned];
                                }

                            });

                            // After assembling json object, send to user:
                            res.json({ 'status': 'success', 'data': referredUsers} );
                    })
                    .catch(function(error) {
                        var msg = 'Error getting users you have referred. Please contact us.';
                        console.info(msg + ' ', error);
                        res.json({ 'status': 'error', 'message': msg });
                    });
            }

        })
        .catch(function(error) {
            var msg = '';
            console.info(msg);
            res.json({ 'status': 'error', 'message': msg });
    });

}
};

Код никогда не достигает блока .then(). console.info('Size: ' + querySnapshot.size); не печатается в журнале Stackdriver.

Здесь вы показываете только частичную функцию. Отредактируйте вопрос, который показывает код полный, минимальный, воспроизводящий проблему, чтобы мы могли видеть всю картину.

Doug Stevenson 27.12.2018 19:05

@DougStevenson Я добавил весь соответствующий код. Это из моего index.js и полная функция того, что я пытаюсь сделать. Спасибо, что посмотрели!

Nick H 02.01.2019 00:04

Как вы думаете, сколько пользователей соответствуют запросу? Что, если вы запустите тот же запрос в процессе узла на своем рабочем столе?

Doug Stevenson 02.01.2019 00:26

Это может быть зацепка firebase.google.com/docs/firestore/quotas Вы следили за своими квотами?

Kevin Coulibaly 02.01.2019 00:35

@DougStevenson есть только 1 пользователь, который соответствует запросу, только 2 пользователя во всей базе данных, поскольку я просто тестирую эту функцию. На рабочем столе еще не тестировал, попробую.

Nick H 02.01.2019 01:25

@kevincoulibaly Я использую тарифный план Blaze, но, тем не менее, у меня недостаточно бесплатной квоты. Менее 100 в день.

Nick H 02.01.2019 01:26

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

Doug Stevenson 02.01.2019 01:27

@DougStevenson Я пробовал это на своем локальном компьютере, он работает, как ожидалось. Я поменял res.json s на console.info s. Он распечатывает данные для 1 найденной записи, а затем распечатывает массив referUsers с элементом 1.

Nick H 02.01.2019 04:10

Тогда это может быть проблема с тем, что вы передаете в res.json ().

Doug Stevenson 02.01.2019 04:21

@DougStevenson сразу после того, как я звоню в БД, у меня есть console.info('Size: ' + querySnapshot.size);, который никогда не печатается в журнале, поэтому он ошибается на .get() в БД.

Nick H 02.01.2019 05:17

Не знаю, что тебе сказать, извини. Убедитесь, что все ваши библиотеки обновлены. Начните с самого простого примера и постепенно продвигайтесь к чему-то более сложному. Люди все время делают запросы к Firestore, поэтому он не является принципиально нарушенным.

Doug Stevenson 02.01.2019 05:18
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
11
1 106
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Решено.

Если кто-нибудь знает, что Зачем работает, дайте мне знать.

Итак, моя переменная var referredUsers = []; создается до того, как я обращаюсь к базе данных Firestore. Когда мой запрос находит совпадение, он добавляет такие данные в указанныйUsers: referredUsers[id] = [username, earned];, который обрабатывает referredUsers как словарь / объект, а не как массив. Это отлично работало на моем локальном компьютере, и напечатало referUsers как: [ <274940135 empty items>, [ 'areliven', 'Yes' ] ], что выглядит странно, и я не совсем понимаю. Но почему-то это заставляло меня превышать лимит памяти при работе в облачной функции Firebase.

Как я это исправил

Поменял var referredUsers = []; на var referredUsers = {}; вот и все! Теперь локально он распечатывает { '274940135': [ 'areliven', 'Yes' ] } и отлично работает с облачными функциями Firebase.

Опять же, если бы кто-нибудь мог пролить свет на то, как это могло заставить меня превысить лимит памяти на Firebase, было бы здорово узнать!

Как вы уже выяснили, массивы JavaScript - это особые типы объектов, поэтому вы можете рассматривать их как словарь, даже если это не совсем его использование. В вашем случае, если ваш ключ словаря - '274940135', и вы затем получите размер referredUsers с referredUsers.lenght, вы увидите, что массив сообщает вам, что он имеет длину '274940136', даже если он имеет 1 элемент. Я думаю, что среда выполнения CF резервирует место в памяти для вашего динамического массива элементов '274940136', который, вероятно, превышает предел памяти.

jpunk11 06.03.2020 13:36

Другие вопросы по теме