我想在使用给定的 uid 首次插入 Cloud Firestore 文档时触发 Cloud Function
以下代码在插入 newUserId 时触发
functions.firestore
.document(`teamProfile/{teamId}/teamMemberList/{newUserId}`)
.onCreate()
要求--
- 文件:帖子
- 字段:id、标题、uid
id 是文档 ID。
在这里,如果这是 uid(user) 的第一个帖子,则应触发云函数。
最佳答案
编辑后的回复(以下是评论中的澄清):
数据结构:
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;
});
}
<小时/>
原始回复(针对每个团队私有(private)的帖子):
假设:
- 检查用户在特定团队而非平台范围内的第一篇帖子。
- 未知的数据结构 - 我使用了我认为适合您现有结构的数据结构。
数据结构:
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;
});
}
注释:
- 以上代码并不完整idempotent 。如果同一用户的多个帖子同时上传,则
handleFirstPost*
函数可能会被多次调用。 - 以上代码未考虑missing documents returned from
listDocuments()
在getCollectionSize()
函数中。在上面的示例中,这不是问题,因为{userId}/posts
集合没有任何子集合。不过,如果您在其他地方调用它,请务必小心。 - 不包含错误处理
- 使用
async
/await
语法可以使其更简洁 - 以上代码是在未部署的情况下编写的,可能存在错误/拼写错误
关于node.js - 使用给定的 uid 首次插入 Cloud Firestore 文档时触发 Firebase Cloud 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58713425/