Angular Firestore:在获取集合时将 DocumentReference 属性映射到对象
Angular Firestore: Map DocumentReference attribute to object while fetching collection
我有一个实体:
export interface FriendRequest {
sender: Profile;
recipient: Profile;
isAccepted: boolean;
dateSend: Date;
dateAccepted?: Date;
}
这就是这些实体在 firestore 中的保存方式:
问题:
我想从 friend-request
集合中获取所有文档,并将 recipient
、sender
从 DocumentReference
类型映射到 Profile
对象。
我试过了。这是我获取所有 friend-request
文档的方法:
listenOnReceivedFriendRequests(profileId: string): Observable<Array<FriendRequest>> {
const myProfileReference = this.$db.doc(`${PROFILE_COLLECTION}/${profileId}`);
return this.$db.collection<FriendRequest>(
FRIEND_REQUEST_COLLECTION,
ref => ref.where('recipient', '==', myProfileReference.ref)
)
.valueChanges()
.pipe(
map((friendRequests) => {
return friendRequests.map((friendRequest) => {
// This is the place where it goes wrong I guess
return {
...friendRequest,
sender: friendRequest.sender.get().then((senderDoc) => friendRequest.sender = senderDoc.data()),
recipient: friendRequest.recipient.get().then((senderDoc) => friendRequest.recipient = senderDoc.data())
};
});
}),
tap(result => console.log(result))
);
}
但它 returns:
[
{
sender: ZoneAwarePromise, // <-- Instead of Profile object
recipient: ZoneAwarePromise, // <-- Instead of Profile object
isAccepted: ...,
dateSend: ...,
dateAccepted: ...,
},
{
sender: ZoneAwarePromise, // <-- Instead of Profile object
recipient: ZoneAwarePromise, // <-- Instead of Profile object
isAccepted: ...,
dateSend: ...,
dateAccepted: ...,
},
]
而不是我的要求的输出:
[
{
sender: Profile,
recipient: Profile,
isAccepted: ...,
dateSend: ...,
dateAccepted: ...,
},
{
sender: Profile,
recipient: Profile,
isAccepted: ...,
dateSend: ...,
dateAccepted: ...,
},
]
我知道我应该等到 sender
和 recipient
的承诺完成,但我不知道如何做到 return 我需要的输出。
而不是 map
运算符,您可以像下面这样处理它:
- 使用 higher-order RxJS mapping operators 之一,将每个
FriendRequest
映射到 Observable
。
- 每个
Observable
将通过使用 [=27= 将两个 Promise
(s) 合并为一个 Observable
来获取相关的 sender
和 recipient
]函数)
- 然后将每个
Observable
结果再次映射到 FriendRequest
对象。
- 将
Observable
的结果数组用forkJoin
函数包装起来,最后变成returnArray<FriendRequest
.
尝试如下操作:
// import { forkJoin, from, Observable } from 'rxjs';
// import { map, mergeMap } from 'rxjs/operators';
listenOnReceivedFriendRequests(
profileId: string
): Observable<Array<FriendRequest>> {
const myProfileReference = this.$db.doc(
`${PROFILE_COLLECTION}/${profileId}`
);
return this.$db
.collection<FriendRequest>(FRIEND_REQUEST_COLLECTION, (ref) =>
ref.where('recipient', '==', myProfileReference.ref)
)
.valueChanges()
.pipe(
mergeMap((friendRequests: Array<FriendRequest>) =>
// forkJoin returns Observable<Array<FriendRequest>>
forkJoin(
// map each item to an Observable<FriendRequest>, after resolving the related profiles.
friendRequests.map((friendRequest) =>
forkJoin({
senderDoc: from(friendRequest.sender.get()),
recipientDoc: from(friendRequest.recipient.get()),
}).pipe(
map(({ senderDoc, recipientDoc }) => ({
...friendRequest,
sender: senderDoc.data(),
recipient: recipientDoc.data(),
}))
)
)
)
)
);
}
我有一个实体:
export interface FriendRequest {
sender: Profile;
recipient: Profile;
isAccepted: boolean;
dateSend: Date;
dateAccepted?: Date;
}
这就是这些实体在 firestore 中的保存方式:
问题:
我想从 friend-request
集合中获取所有文档,并将 recipient
、sender
从 DocumentReference
类型映射到 Profile
对象。
我试过了。这是我获取所有 friend-request
文档的方法:
listenOnReceivedFriendRequests(profileId: string): Observable<Array<FriendRequest>> {
const myProfileReference = this.$db.doc(`${PROFILE_COLLECTION}/${profileId}`);
return this.$db.collection<FriendRequest>(
FRIEND_REQUEST_COLLECTION,
ref => ref.where('recipient', '==', myProfileReference.ref)
)
.valueChanges()
.pipe(
map((friendRequests) => {
return friendRequests.map((friendRequest) => {
// This is the place where it goes wrong I guess
return {
...friendRequest,
sender: friendRequest.sender.get().then((senderDoc) => friendRequest.sender = senderDoc.data()),
recipient: friendRequest.recipient.get().then((senderDoc) => friendRequest.recipient = senderDoc.data())
};
});
}),
tap(result => console.log(result))
);
}
但它 returns:
[
{
sender: ZoneAwarePromise, // <-- Instead of Profile object
recipient: ZoneAwarePromise, // <-- Instead of Profile object
isAccepted: ...,
dateSend: ...,
dateAccepted: ...,
},
{
sender: ZoneAwarePromise, // <-- Instead of Profile object
recipient: ZoneAwarePromise, // <-- Instead of Profile object
isAccepted: ...,
dateSend: ...,
dateAccepted: ...,
},
]
而不是我的要求的输出:
[
{
sender: Profile,
recipient: Profile,
isAccepted: ...,
dateSend: ...,
dateAccepted: ...,
},
{
sender: Profile,
recipient: Profile,
isAccepted: ...,
dateSend: ...,
dateAccepted: ...,
},
]
我知道我应该等到 sender
和 recipient
的承诺完成,但我不知道如何做到 return 我需要的输出。
而不是 map
运算符,您可以像下面这样处理它:
- 使用 higher-order RxJS mapping operators 之一,将每个
FriendRequest
映射到Observable
。 - 每个
Observable
将通过使用 [=27= 将两个Promise
(s) 合并为一个Observable
来获取相关的sender
和recipient
]函数) - 然后将每个
Observable
结果再次映射到FriendRequest
对象。 - 将
Observable
的结果数组用forkJoin
函数包装起来,最后变成returnArray<FriendRequest
.
尝试如下操作:
// import { forkJoin, from, Observable } from 'rxjs';
// import { map, mergeMap } from 'rxjs/operators';
listenOnReceivedFriendRequests(
profileId: string
): Observable<Array<FriendRequest>> {
const myProfileReference = this.$db.doc(
`${PROFILE_COLLECTION}/${profileId}`
);
return this.$db
.collection<FriendRequest>(FRIEND_REQUEST_COLLECTION, (ref) =>
ref.where('recipient', '==', myProfileReference.ref)
)
.valueChanges()
.pipe(
mergeMap((friendRequests: Array<FriendRequest>) =>
// forkJoin returns Observable<Array<FriendRequest>>
forkJoin(
// map each item to an Observable<FriendRequest>, after resolving the related profiles.
friendRequests.map((friendRequest) =>
forkJoin({
senderDoc: from(friendRequest.sender.get()),
recipientDoc: from(friendRequest.recipient.get()),
}).pipe(
map(({ senderDoc, recipientDoc }) => ({
...friendRequest,
sender: senderDoc.data(),
recipient: recipientDoc.data(),
}))
)
)
)
)
);
}