这是我的数据库结构:
-threadsMeta
-posts
-postId
-votes
-threadId
-postId
-uid: "down" //or "up"
我认为以下代码中的注释描述了预期的行为与实际行为。
getMyUpVotes(threadId: string, uid: string): Observable<any> {
//Get all the postId's for this thread
let myUpVotes = this.af.database.list(`threadsMeta/${threadId}/posts`)
.map(posts => {
//Put each postId into a Firebase query path along with the uid from the method's params
posts.forEach(post => {
this.af.database.object(`votes/${threadId}/${post.$key}/upVotes/${uid}`)
//Emit only upvotes from this user on this post
.filter(data => data.$value === true)
})
})
myUpVotes.subscribe(data => console.log(data)) //Undefined
return myUpVotes
}
答案 0 :(得分:1)
以下方法将为给定用户返回给定线程+的upvote +的帖子数组:
getMyUpVotes(threadId: string, uid: string): Observable<any> {
return this.af.database.list(`threadsMeta/${threadId}/posts`).take(1)
// Flatten the posts array to emit each post individually.
.mergeMap(val => val)
// Fetch the upvotes for the current user on the current post.
.mergeMap(post =>
this.af.database.object(`votes/${threadId}/${post.$key}/upVotes/${uid}`).take(1)
// Only keep actual upvotes
.filter(upvote => upvote.$value === true)
// Convert the upvote to a post, since this is the final value to emit.
.map(upvote => post)
)
// Gather all posts in a single array.
.toArray();
}
我添加了.take(1)
以强制完成Firebase可观察项,以便可以使用toArray()
收集最终结果。这也意味着一旦你获得了赞成票,你就会停止观察未来的价值变化。如果这是一个问题,请告诉我。
重要。您应该从方法的OUTSIDE订阅observable。
我创建了一个可运行的版本来说明(请注意,我使用的是普通的observable,因为在这种环境下,Angular和Firebase都不可用):
const getPostsForThread = (threadId) => {
return Rx.Observable.of([
{ key: 'jcormtp', title: 'Some post', threadId: threadId },
{ key: 'qapod', title: 'Another post', threadId: threadId },
{ key: 'bvxspo', title: 'Yet another post', threadId: threadId }
]);
}
const getUpvotesPerPostPerUser = (postId, uid) => {
return Rx.Observable.from([
{ postId: 'jcormtp', uid: 'bar', value: true },
{ postId: 'qapod', uid: 'bar', value: false },
{ postId: 'bvxspo', uid: 'bar', value: true }
]).filter(uv => uv.postId == postId && uv.uid == uid);
}
const getMyUpVotes = (threadId: string, uid: string): Rx.Observable<any> => {
return getPostsForThread(threadId)
// Flatten the posts array to emit each post individually.
.mergeMap(val => val)
// Fetch the upvotes for the current user on the current post.
.mergeMap(post =>
getUpvotesPerPostPerUser(post.key, uid)
// Only keep actual upvotes
.filter(upvote => upvote.value === true)
// Convert the upvote to a post, since this is the final value to emit
.map(upvote => post)
)
// Gather all posts in a single array
.toArray();
}
// NB. subscribe() outside of the method
getMyUpVotes('foo', 'bar')
.subscribe(val => console.log(val));
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.0.1/Rx.min.js"></script>
答案 1 :(得分:0)
我想你想要:
let myUpVotes = this.af.database.list(`threadsMeta/${threadId}/posts`)
.flatMap(posts =>
Observable.from(posts)
.flatMap(post=>this.af.database.object(
`votes/${threadId}/${post.$key}/upVotes/${uid}`));
myUpVotes = myUpVotes.flatMap(t=>t.filter(x=>x.uid === true));
答案 2 :(得分:0)
所以我确实想出了一个适合我特殊情况的解决方案。我只是不太了解observables知道它是否是最好的方法。无论如何,我最终用我的帖子查询'加入'查询。这适用于我的特定情况,因为我使用ngFor
呈现帖子。我能够检查当前用户是否已对此特定帖子进行了投票/投票:
<i [class.voted]="post.vote === 'down'" class="fa fa-caret-down" aria-hidden="true"></i>
以下是我获取数据的方式:
getPosts(threadId: string, uid: string): Observable<any> {
let result = this.af.database.list(`/threads/${threadId}/posts`)
.switchMap(posts => {
let joinedObservables: any[] = [];
posts.forEach(post => {
joinedObservables.push(this.af.database
.object(`votes/${threadId}/${post.$key}/${uid}`)
.do(value => {
post.vote = value.$value
})
)
})
return Observable.combineLatest(joinedObservables, () => posts);
});
return result
}
在这个实现中,我不断从投票中获得排放,这很重要,因为用户投票必须反映在页面上,不仅仅是在加载,而且如果他们改变了投票。
我想知道是否有人预见到这方面的任何问题。我对这项技术并不擅长,我想知道我是否遗漏了任何东西。我会给那些已经回答机会发表任何反对意见的人,并在选择这个答案之前编辑他们自己想要的答案。