基于geofireX的位置的内部联接集合

问题描述

我想使用geofirex根据用户的位置获取并加入多个集合:

这是我根据位置获取用户文档时的代码: 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)))