Запустить облачную функцию Firebase при первой вставке в документ Cloud Firestore с указанным идентификатором пользователя - PullRequest
1 голос
/ 05 ноября 2019

Я хочу запустить Cloud Funtion при первой вставке в документ Cloud Firestore с указанным uid

Приведенный ниже код срабатывает при вставке newUserId

functions.firestore
  .document(`teamProfile/{teamId}/teamMemberList/{newUserId}`)
  .onCreate()

Требование -

  • Документ: Post
  • Поля: id, title, uid

id - это идентификатор документа.

Здесь функция Cloudдолжен сработать, если это первое сообщение от пользователя uid.

1 Ответ

1 голос
/ 05 ноября 2019

Отредактированный ответ (после пояснения в комментариях):

Структура данных:

users/{userId}/posts/
 ◙ post18sfge89s
   - title: My first post!
   - t: 1572967518
 ◙ post2789sdjnf
   - title: I like posting
   - t: 1572967560

posts/
 ◙ post18sfge89s
   - title: My first post!
   - uid: someUid1
   - comments/
     ◙ comment237492384
       ...
     ◙ comment234234235
       ...
 ◙ post2789sdjnf
   - title: I like posting
   - uid: someUid1

Код функции облака:

С вышеуказанной структуройдля управления вам понадобятся две облачные функции - одна для обработки каждого нового сообщения (для копирования информации в список публикаций автора) и одна для проверки того, является ли это первое сообщение автора.

// Function: New post handler
exports.newPost = functions.firestore
  .document('posts/{postId}')
  .onCreate((postDocSnap, context) => {

    // get relevant information
    const postId = postDocSnap.id; // provided automatically
    const postTitle = postDocSnap.get('title');
    const userId = postDocSnap.get('uid');
    const postedAt = postDocSnap.createTime; // provided automatically

    // add to user's post list/index
    return firestore.doc(`users/${userId}/posts/${postId}`)
      .set({
        title: postTitle,
        t: postedAt
      });
  });

// Function: New post by user handler
exports.newPostByUser = functions.firestore
  .document('users/{userId}/posts/{postId}')
  .onCreate((postDocSnap, context) => {

    // get references
    const userPostsColRef = postDocSnap.ref.parent;
    const userDocRef = userPostsCol.parent;

    // get snapshot of user data
    return userDocRef.get()
      .then((userDocSnap) => {

        // check if "First Post Event" has already taken place
        if (userDocSnap.get('madeFirstPostEvent') != true) {
          return getCollectionSize(userPostsColRef).then((length) => {
            if (length == 1) {
              return handleFirstPostByUser(userDocSnap, postDocSnap);
            } else {
              return; // could return "false" here
            }
          });
        }
      });
  });

// Pseudo-function: First post by user handler
function handleFirstPostByUser(userDocSnap, postDocSnap) {
  return new Promise(() => {
      const postId = postDocSnap.id;
      const postTitle = postDocSnap.get('title');
      const userId = userDocSnap.id;

      // do something

      // mark event handled
      return userDocSnap.ref.update({madeFirstPostEvent: true});
    });
}

// returns a promise containing the length of the given collection
// note: doesn't filter out missing (deleted) documents
function getCollectionSize(colRef) {
  return colRef.listDocuments()
     .then(docRefArray => {
       return docRefArray.length;
     });
}


Исходный ответ (для сообщений, которые являются частными для каждой команды):

Допущения:

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

Структура данных:

Структура teamContent/ структурированатак что он может содержать вложенные коллекции для различных элементов, таких как сообщения, вложения, рисунки и т. д.

teamProfile/{teamId}/teamMemberList/{userId}/posts/
 ◙ post18sfge89s
   - title: My first post!
   - t: 1572967518
 ◙ post2789sdjnf
   - title: I like posting
   - t: 1572967560

teamContent/{teamId}/posts/
 ◙ post18sfge89s
   - title: My first post!
   - author: someUid1
   - comments/
     ◙ comment237492384
       ...
     ◙ comment234234235
       ...
 ◙ post2789sdjnf
   - title: I like posting
   - author: someUid1

Код функции облака:

С приведенной выше структурой вам понадобятся две функции облака дляУправляй этим - один для обработки каждого нового сообщения (для копирования информации в список сообщений автора) и один для проверки, является ли это первое сообщение автора в этой конкретной команде.

// Function: New team post handler
exports.newPostInTeam = functions.firestore
  .document('teamContent/{teamId}/posts/{postId}')
  .onCreate((postDocSnap, context) => {

    // get relevant information
    const postId = postDocSnap.id; // provided automatically
    const postTitle = postDocSnap.get('title');
    const authorId = postDocSnap.get('author');
    const postedAt = postDocSnap.createTime; // provided automatically
    const teamId = context.params.teamId;

    // add to user's post list/index
    return firestore.doc(`teamProfile/${teamId}/teamMemberList/${authorId}/posts/${postId}`)
      .set({
        title: postTitle,
        t: postedAt
      });
  });

// Function: New post by team member handler
exports.newPostByTeamMember = functions.firestore
  .document('teamProfile/{teamId}/teamMemberList/{userId}/posts/{postId}')
  .onCreate((postDocSnap, context) => {

    // get references
    const userPostsColRef = postDocSnap.ref.parent;
    const userDocRef = userPostsCol.parent;

    // get snapshot of user data
    return userDocRef.get()
      .then((userDocSnap) => {

        // check if "First Post Event" has already taken place
        if (userDocSnap.get('madeFirstPostEvent') != true) {
          return getCollectionSize(userPostsColRef).then((length) => {
            if (length == 1) {
              return handleFirstPostInTeamEvent(userDocSnap, postDocSnap);
            } else {
              return; // could return "false" here
            }
          });
        }
      });
  });

// Pseudo-function: First post by team member handler
function handleFirstPostInTeamEvent(userDocSnap, postDocSnap) {
  return new Promise(() => {
      const postId = postDocSnap.id;
      const postTitle = postDocSnap.get('title');
      const userId = userDocSnap.id;

      // do something

      // mark event handled
      return userDocSnap.update({madeFirstPostEvent: true});
    });
}

// returns a promise containing the length of the given collection
// note: doesn't filter out missing (deleted) documents
function getCollectionSize(colRef) {
  return colRef.listDocuments()
     .then(docRefArray => {
       return docRefArray.length;
     });
}


Примечания:

  • Приведенный выше код не является полностью идемпотентным . Если несколько сообщений от одного и того же пользователя загружены одновременно, существует вероятность, что функции handleFirstPost* будут вызываться несколько раз.
  • Выше код не учитывает пропущенных документов, возвращенных из listDocuments() в функции getCollectionSize(). Это не относится к приведенному выше образцу, поскольку коллекция {userId}/posts не имеет вложенных коллекций. Будьте осторожны, если вы вызываете его в другом месте.
  • Не включена обработка ошибок
  • Использование синтаксиса async / await может сделать его чище
  • Выше был написан кодбез его развертывания могут присутствовать ошибки / опечатки
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...