我正在浏览Firestore文档和指南。我下面的代码示例使用AngularFire2。
让我们考虑一下"聊天"与此处提供的示例类似的集合:https://firebase.google.com/docs/firestore/manage-data/structure-data
他们推荐这种结构,但我不知道他们在哪里讨论如何有效地获取所有数据。
每个聊天文档都有属性,成员集合和消息集合:
Firestore查询很浅,有时可能很棒。我的理解是,没有编程方式来深入查询并获得嵌套集合。那么,最好的做法和最无障碍的方法是什么?
目前,我正在检索快照并将其映射到具有ID的对象,并将嵌套的集合数据添加到父文档数据中,并附加查询和映射,并且我对我的方法不满意,并且可以即使使用非规范化的Firebase结构,也可以更快地完成。
这个代码示例只是映射成员,在消息中添加回来是另一个故事...
getChatsFromFirestore() {
this.chats = this.dataSvc.getChatsFromFirestore().snapshotChanges()
.map(chatSnaps => {
return chatSnaps.map(chat => {
const chatData = chat.payload.doc.data();
const chatId = chat.payload.doc.id;
return this.dataSvc.getMembersForChat(chatId)
.snapshotChanges()
.map(memberSnaps => {
return memberSnaps.map(member => {
const data = member.payload.doc.data();
const id = member.payload.doc.id;
return { id, ...data }
});
})
.map(members => {
return { chatId, ...chatData, members: members };
});
})
})
.flatMap(chats => Observable.combineLatest(chats));
}
来自服务:
getChatsFromFirestore() {
return this.fsd.collection<any>('chats');
}
getChatFromFirestoreById(id: string) {
return this.fsd.doc(`chats/${id}`);
}
getMembersForChat(chatId) {
return this.getChatFromFirestoreById(chatId).collection('members');
}
答案 0 :(得分:0)
您发布的方法似乎会起作用,对于大型聊天应用程序,您可能不希望跟踪每个聊天室中发生的每个事件,因为这可能是大量数据。相反,最好只订阅所需内容并使用云功能和云消息处理定期更新。
通过使用辅助函数observeCollection
以及小代码重构,它将清理服务并为每个聊天室创建observable,这些聊天室在订阅之前将处于非活动状态。
class Service {
// db is plan firestore / no angularfire
db: firebase.firestore.Firestore;
loadChatrooms() {
const chatsRef = this.db.collection('chats');
return observeCollection(chatsRef)
.pipe(
map(chats => {
return chats.map(chat => {
return {
chat,
members$: this.observeCollection(chat.ref.collection('members')),
messages$: this.observeCollection(chat.ref.collection('messages')),
};
})
}),
);
}
// Takes a reference and returns an array of documents
// with the id and reference
private observeCollection(ref) {
return Observable.create((observer) => {
const unsubscribeFn = ref.onSnapshot(
snapshot => {
observer.next(snapshot.docs.map(doc => {
const data = doc.data();
return {
...doc.data(),
id: doc.id,
ref: doc.ref
};
}));
},
error => observer.error(error),
);
return unsubscribeFn;
});
}
}
在应用程序中,您只能观察当前选定的聊天室成员和消息,这将保存数据。 由于此帖子标有Angular异步管道,因此可以通过自动手动下标来帮助切换。
在您的组件中:
this.currentChat$ = combineLatest(
service.loadChatrooms(),
currentlySelectedRoomId
).pipe(
map(([chats, selectedRoomId]) => {
return chats.first(chat => chat.id === selectedRoomId)
})
);
在你的模板中:
<div *ngIf="currentChat$ as currentChat">
{{ currentChat.name }}
<div *ngIf="currentChat.members$ as members">
<div *ngIf="let member of members">
{{ member.name }}
</div>
</div>
<div *ngIf="currentChat.messages$ as messages">
<div *ngIf="let message of messages">
{{ message.content }}
</div>
</div>
</div>