使用 angularfire2 查询 Firebase 实时数据库上的数据关系 [英] Query data relationship on Firebase Realtime Database with angularfire2
问题描述
我需要查询评论并仅请求通过 userId 在评论中列出的用户.
I need to query comments and request only user that listed in the comment by userId.
我在 Firebase 实时数据库中的数据库结构:
My database structure in Firebase realtime db:
{
"comments" : {
"c_id1" : {
"commentId" : "c_id1",
"commentText" : "text",
"userId" : "u_id1"
},
"c_id2" : {
"commentId" : "c_id2",
"commentText" : "text",
"userId" : "u_id3"
},
},
"users" : {
"u_id1" : {
"userId" : "u_id1",
"userName" : "name1",
},
"u_id1" : {
"userId" : "u_id2",
"userName" : "name2",
},
"u_id1" : {
"userId" : "u_id3",
"userName" : "name3",
}
}
}
我最后需要的是Comment[],其中Comment是:
What I need in the end is Comment[], where Comment is:
{
"commentId" : "c_id",
"commentText" :"text",
"userId" : "u_id",
"user" : {
"userId":"u_id",
"userName":"name"
}
}
所以,Comment 的类是
so, the class for Comment is
export class Comment {
commentId: string;
commentText: string;
userId: string;
user?: User;
}
到目前为止,我设法获取了所有用户,然后将它们映射到客户端的评论.但是,如果 db 有 N 个用户,只有 2 个评论,其中 N>>2,那岂不是太多了?
So far I managed to get ALL users and then map them to comments on the client side. But wouldn't it be to much in case when db will have N number of users and only 2 comments, where N>>2?
OnGetUsersForComments(){
return this.angularFireDatabase.list("/comments").valueChanges()
.subscribe((data) => {
this.commentsUsers = data;
this.OnGetCommentsForTask()
});
}
OnGetCommentsForTask(){
this.angularFireDatabase.list("/comments").valueChanges()
.map((comments) => {
return comments.map( (comment: TaskComment) => {
this.commentsUsers.forEach((user: User) => {
if (comment.userId === user.userId) {
comment.commentUser = user;
}
});
return comment;
});
})
.subscribe((data)=> {
this.comments = data;
});
}
有没有办法只从评论中获取用户?
Is there a way get only users from comments?
我也尝试将其添加到用户中,但未能使其正常工作:
I also tried to add this to the User, but did not manage it to work:
"userComments" : {
"uc_id1" : {
"commentId" : c_id2
},
}
<小时>
更新 0
我已经编辑了问题,我希望现在更清楚了.
I have edited the question, I hope now is more clear.
我已经能够让它像这样工作:来自 - https://www.firebase.com/docs/web 的解决方案/guide/structuring-data.html和https://firebase.google.com/docs/database/web/读写
I have been able to make it work like this: solution from - https://www.firebase.com/docs/web/guide/structuring-data.html and https://firebase.google.com/docs/database/web/read-and-write
comments: TaskComment[] = [];
onGetComments(){
var ref = firebase.database().ref('/');
ref.child('comments/').on('child_added', (snapshot)=>{
let userId = snapshot.val().userId;
ref.child('users/' + userId).on('value', (user)=>{
this.comments.push( new TaskComment( snapshot.val(), user.val() ));
});
});
}
但我想将其转换为 Observable,因为这样我无法在不刷新页面的情况下查看评论是否已被删除.
but I want to convert this to Observable, because with this I can not see if the comment have been deleted without refreshing the page.
更新 1
在下面评论的帮助下,我提出了这个实现.
With the help from comment bellow I came out with this implementation.
onGetComments(){
this.angularFireDatabase.list("/comments").valueChanges()
.mergeMap((comments) => {
return comments.map((comment)=>{
this.firebaseService
.onListData('/users', ref => ref.orderByChild('userId').equalTo(comment.userId))
.valueChanges()
.subscribe((user: User[])=> {
comment.user = user[0];
})
return comment;
})
})
.subscribe((comment)=> {
console.log(comment);
});
}
这将返回单独的评论,我宁愿在其中接收 Comment[],我将尝试使用子事件:child_ added"、child_changed"、child_removed"和child_moved"与 snapshotChanges() 代替 .valueChanges().
This returns separate comments, where I would rather receive Comment[], I'll try to use child events: "child_added", "child_changed", "child_removed", and "child_moved" with snapshotChanges() instead .valueChanges().
推荐答案
好吧,根据你的更新,我个人会先创建几个辅助接口:
Ok so according to your updates, I would personally first create a couple helper interfaces:
interface User {
userId: string;
userName: string;
}
interface FullComment {
commentId: string;
userId: string;
user: User;
}
interface CommentObject {
commentId: string;
commentText: string;
userId: string;
}
然后是超级方便的辅助方法:
And then super handy helper methods:
getUser(uid: string): Observable<User> {
return this.db.object<User>(`/users/${uid}`)
.valueChanges()
}
getFullComment(commentObject: CommentObject): Observable<FullComment> {
return this.getUser(commentObject.userId)
.map((user: User) => {
return {
commentId: commentObject.commentId,
commentText: commentObject.commentText,
user: user,
};
});
}
最后看看获取 FullComment 对象是多么容易观察:
So finally look how easy it becomes to get the FullComment objects observable:
getComments(): Observable<FullComment[]> {
return this.db
.list(`/comments`)
.valueChanges()
.switchMap((commentObjects: CommentObject[]) => {
// The combineLatest will convert it into one Observable
// that emits an array like: [ [fullComment1], [fullComment2] ]
return Observable.combineLatest(commentObjects.map(this.getFullComment));
});
}
我认为这就是您所需要的.请让我知道这是否有帮助.使用 observable 进行愉快的编码 ;)
I think this is what you need. Please let me know if this is helpful. Happy coding with observables ;)
最新更新:之前忘记做最后一次转换来修复TypeError,所以现在应该没问题了.
Latest update: Previously forgot to make a last transformation to fix the TypeError, so now it must be ok.
这篇关于使用 angularfire2 查询 Firebase 实时数据库上的数据关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!