Как загрузить 2 разных документа Firestore в одну облачную функцию onUpdate? - PullRequest
0 голосов
/ 28 октября 2019

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

Я хочу: /userProfiles/{doc1}/employees/{doc2} AND /userProfiles/{doc1}.

Я могу получить их обоихно когда я пытаюсь использовать данные одного из них, он не читает предыдущие данные и дает мне ReferenceError.

Конечная цель - использовать оба этих документа для отправки электронного письма с помощью nodemailer. Спасибо за любую помощь.


const functions = require("firebase-functions");
const admin = require("firebase-admin");
const nodemailer = require('nodemailer');
admin.initializeApp();

exports.testLog = functions.firestore
  .document('/userProfiles/{doc1}/employees/{doc2}')
  .onUpdate((change, context) => {
    var info = [];
    const doc1 = context.params.doc1;
    const doc2 = context.params.doc2;

    const db = admin.firestore();

    return (
      db
        .collection("userProfiles")
        .doc(`${doc1}`)
        .get()
        .then(doc => {
          var email = doc.data().email;
          var phone = doc.data().phone;

          info.push(doc.data());

          console.log(email, phone); // sees and gets info

          return email, phone;
        }),
      db
        .collection("userProfiles")
        .doc(`${doc1}`)
        .collection(`employees`)
        .doc(`${doc2}`)
        .get()
        .then(doc => {
          info.push(doc.data());

          var Status = doc.data().Status;

          console.log(phone, `${Status}`); //phone is undefined

          if (`${Status}` === "Alarm") {
            // replace with variables from the users settings page

            console.log(`${info.phone}`); // phone is undefined

            let transporter = nodemailer.createTransport({
              host: "smtp.gmail.com",
              port: 587,
              secure: false, 
              auth: {
                user: "xxxxxx@gmail.com",
                pass: "xxxxxxxxxx"
              }
            });

            // send mail with defined transport object
            let mailOptions = {
              from: '"Fred Foo ?" <foo@example.com>', 
              to: `${info.phone}`,  // tried phone as well
              subject: "Hello ✔", 
              text: "216+?", 

            };

            transporter.sendMail(mailOptions, error => {
              if (error) {
                return console.log(error);
              } else {
                return console.log("message sent");
              }
            });
          }

          console.log(Status);
          // return
          return console.log("im after the if statement. No alarm triggered");
        })

        .then(message => console.log(message.sid, "success"))
        .catch(err => console.log(err))
    );
  });

Firestore

subcollection

Итак, я хочу получитьномер телефона и состояние на этих 2 изображениях. Возвращаемая ошибка:

ReferenceError: телефон не определен

1 Ответ

2 голосов
/ 28 октября 2019

Есть две вещи, которые не совсем работают так, как вы ожидаете, что приводит к вашей проблеме:

  • Обработка обещаний на самом деле не передает данные так, как вы ожидаете -в частности, переменные phone и email существуют только в одном обработчике обещаний, они не являются глобальными по объему, поэтому phone и email не передаются по цепочке обещаний.

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

Посмотрите на этот код, где я пропустил код сообщения для ясности и просто оставил на месте большинство сообщений журнала:

exports.firestoreOnUpdateTest = functions.firestore
    .document('/userProfiles/{doc1}/employees/{doc2}')
    .onUpdate((change, context) => {
  // var info = []; I have removed this list, it is not necessary
  const doc1 = context.params.doc1;
  // no need to get the doc2 parameter, as we are handed the doc itself by the function call.

  const doc2content = change.after.data();

  const db = admin.firestore();

  return (
    db
      .collection("userProfiles")
      .doc(`${doc1}`)
      .get()
      .then(doc => {
        const doc1content = doc.data();
        const email = doc1content.email;
        const phone = doc1content.phone;

        console.log(email, phone); // sees and gets info

        console.log(`No need to fetch doc2, as I already have it: ${JSON.stringify(doc2content)}`);
        const Status = doc2content.Status;

        console.log(`email for user is still: ${email}`); // email is now defined
        console.log(phone, `${Status}`); // phone is now defined

        if (`${Status}` === "Alarm") {
          console.log(`${phone}`); // phone is now defined

          return console.log('message would be sent here - code omitted')
        }

        console.log(Status);

        return console.log("im after the if statement. No alarm triggered");
      })
      .catch(err => console.error(err))
  );
});

В новой версии,мы просто храним содержимое документа, который нас вызвал, включая параметр Status. Затем мы получаем документ с необходимым нам содержанием - на более высоком уровне в дереве. Как только этот документ возвращается, мы просто обрабатываем его и объединяем с данными из doc2. Все поля теперь определены (при условии, конечно, что объекты базы данных правильно сформированы).

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

Наконец, список info, который я не считаю необходимым сейчас, поэтому я удалил его. Вместо этого я рекомендую вам создать то, что вам нужно, так как вы создаете само сообщение из уже имеющихся данных. Тем не менее, ваш исходный код не обращался к нему правильно (то есть как список) в любом случае и, возможно, еще больше сбивал вас с толку.

Наконец, я не рассматривал использование модуля Nodemailer в качествеЭтот вопрос был сосредоточен главным образом на неопределенных полях, но я подозреваю, что ваш исходный код может быть не совсем корректным - так как он не возвращает обещание обратно из sendMail() или не выполняет await для этого вызова (и делает весьфункция async), так что вам нужно взглянуть на это более внимательно.

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