问题描述
这是我根据位置获取用户文档时的代码: PS(此代码仅根据位置返回用户的文档)
geTaround() {
const center = geo.point(this.lat,this.lng);
const field = 'location';
this.points = this.radius.pipe(
switchMap(r => {
return this.geo.query(locations).within(center,r,field,{ log: true });
})
);
}
我如何使用Rxjs内部联接集合:
getAll() {
const allPosts = this.afStore.collection<Service>('services')
.valueChanges()
.pipe(
switchMap(services => {
const res = services.map((service: Service) => {
return this.afStore.doc<usermodel>(`users/${service.userId}`)
.valueChanges()
.pipe(
map(user => Object.assign(service,{ user }))
);
});
return combineLatest([...res]); })
)
.pipe(
switchMap(servuser => {
const ress = servuser.map((service: Service) => {
return this.afStore.doc<Category>(`categorys/${service.iconId}`)
.valueChanges()
.pipe(
map(category => Object.assign(service,{ category }))
);
});
return combineLatest([... ress]);
})
);
return allPosts;
}
问题是我无法将这些代码混合在一起,因此我可以根据用户的位置合并数据,
我得到这个error:
(alias) interface Service
import Service
Argument of type '(service: Service) => Observable<Service & { user: usermodel; }>' is not assignable to parameter of type '(value: GeoQueryDocument,index: number,array: GeoQueryOocument[]) => Observable<Service & { user: usermodel; }>'. Types of parameters 'service' and 'value' are incompatible.
Type 'GeoQuerpocument' is missing the following properties from type 'Service': id,cost,dateCreated,discount,and 6 more.
解决方法
添加此修复程序后,我的代码即可正常工作!
.pipe(
switchMap(services => {
const res = services.map((fromservices) => {
return this.afStore.doc<UserModel>(`users/${fromservices['userId']}`)
.valueChanges()
.pipe(
map(user => Object.assign(fromservices,{ user }))
);
});
return combineLatest([...res]); })
)
只有这个警告就可以了吗? :
object access via string literals is disallowed (no-string-literal)tslint(1)
,
错误表明services
来自value-index-array类型,而您暗含的是Services数组。
.pipe(
switchMap(services => { // <-- expects a Service array (but appreantly it's not)
const res = services.map((service: Service) => { // <-- because of this
return this.afStore.doc<UserModel>(`users/${service.userId}`)
.valueChanges()
.pipe(
map(user => Object.assign(service,{ user }))
);
});
return combineLatest([...res]); })
)
,
您可能想看看这个question。他们逐步解释与您类似的情况。
他们还共享了一个DEMO:使用上述代码和模拟FireStore的完整,有效的演示。
除此之外,我发现有关Join Collections in Firestore的内容可能与您有关。
我建议先考虑一下这个问题。无论如何,我将在这里添加一些非凡的东西:
- 您可以使用
pipeable transformation operators
:
const myQuery$ = this.myQuery.onSnapshot.pipe(
map(querySnapshot => querySnapshot.docs.map(d => d.data()))
);
- 要连接这两个查询,
combineLatest
是正确的创建函数。
但是,您的错误可能是由您使用较新的RxJS版本导致的,该版本不再支持
fluent
运算符(正式称为“补丁运算符”)。从RxJS 6开始,它们已被pipeable operators
取代。例如,myObs$.map(...)
变成了myObs$.pipe(map(...))
。这些教程可能会使用RxJS的旧版本,但仍然可以使用第一个版本。
此外,如果内部Observable只是一个操作符,则不必使用
switchMap
。在这种情况下,使用map
运算符就足够了,它们的行为将相同。
使用新的RxJS 6+语法和map,组合将如下所示:
const orQuery$ = combineLatest(myQuery$,publicQuery$).pipe(
map(([one,two]) => one.concat(two))
)
侧面注意:请记住,SQL中的代码等效于UNION(不是JOIN)。为了以编程方式进行JOIN,您需要将结果集A的每个对象与结果集B的每个对象组合在一起,并为每对创建一个联接的对象。这样的无键OUTER JOIN函数看起来像这样(放置在地图管道中):
one.map(a =>
two.map(b => Object.assign({},a,b)))
.reduce((p,c) => p.concat(c),[])
如果要创建一个没有重复对象的UNION,请仅合并两个列表中没有匹配主键的项。这将是您的映射功能:
one.concat(two.filter(twoItem => !one.some(oneItem => oneItem.id == twoItem.id)))