2

我有一个 Firestore 数据库,它的集合排列类似于关系数据库,相关集合存储外键。做出此决定是为了更轻松地与现有 .Net 服务集成,并提供更大的灵活性。

这是数据模型的一部分:

在此处输入图像描述

我已将我的状态拆分为功能模块,并具有如下代码:

  ngxsOnInit(ctx: StateContext<SchedulesStateModel>) {
    ctx.dispatch([
      new GetScheduleGroups(),
      new GetSchedules()
    ]);
  }

  @Selector()
  static scheduleGroups(state: SchedulesStateModel): Array<ScheduleGroup> {
    return state.scheduleGroups;
  }

  @Selector()
  static scheduleGroupById(state: SchedulesStateModel) {
    return (scheduleGroupId: string) => {
      return state.scheduleGroups.filter((scheduleGroup: ScheduleGroup) =>
        scheduleGroup.id === scheduleGroupId);
    };
  }

  @Action(GetScheduleGroups)
  getScheduleGroups({ patchState }: StateContext<SchedulesStateModel>) {
    return this.dataService.getDocuments$<ScheduleGroup>('scheduleGroups')
      .pipe(tap(scheduleGroups => patchState({ scheduleGroups })));
  }

  @Action(GetSchedules)
  getSchedules({ patchState }: StateContext<SchedulesStateModel>) {
    return this.dataService.getDocuments$<Schedule>('schedules')
      .pipe(tap(schedules => patchState({ schedules })));
  }

在 ScheduleListComponent 中,我有以下代码:

  getSchedulesById$(scheduleGroupId: string) {
    return this.store.select(SchedulesState.schedulesByGroupId)
      .pipe(map(schedulesFilter => schedulesFilter(scheduleGroupId)));
  }

我可以将 getSchedulesById$ 的检索逻辑移动到状态类中,但是我目前的代码结构方式是,我需要一种为每个 ScheduleGroup 检索 Schedules 的方法;因为 ScheduleGroup 被迭代并检索每个组的 Schedules 以进行显示。这可以在以下模板片段中看到:

<ngb-tab
  *ngFor="let scheduleGroup of (getScheduleGroups$(scheduleGroupCollection.id) | async)"
  [title]="scheduleGroup.name">
  <ng-template ngbTabContent>
    <div class="schedules-container" [ngStyle]="{ height: tabHeight }">
      <ibms-schedules-list-item
        *ngFor="let schedule of (getSchedules$(scheduleGroup.id) | async)"
        [schedule]="schedule">
      </ibms-schedules-list-item>
    </div>
  </ng-template>
</ngb-tab>

这段代码有效,但看起来很冗长。有没有更好的方法来做到这一点?

我遇到的问题之一是,即使是简单的组件最终也会变成容器。以 ScheduleListComponent 为例,它需要显示来自相关表的数据。获取此数据取决于在 *ngFor 迭代期间哪个特定的 Schedule 项处于焦点。

有什么改进的建议吗?我几乎可以肯定有更好的方法,但我不确定它是什么。

另外,这里是数据服务:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { fromPromise } from 'rxjs/internal-compatibility';
import { map } from 'rxjs/operators';

import { AngularFirestore } from 'angularfire2/firestore';
import WhereFilterOp = firebase.firestore.WhereFilterOp;

import { Guid } from 'guid-typescript';

@Injectable({
  providedIn: 'root'
})
export class DataService {

  constructor(private db: AngularFirestore) {}

  getDocuments$<T>(collectionName: string): Observable<T[]> {
    return this.db.collection<T>(collectionName).snapshotChanges().pipe(
      map(actions => actions.map(action => {
        const id = action.payload.doc.id;
        const data: T = action.payload.doc.data() as T;
        data[ 'id' ] = id;
        return <T>data;
      }))
    );
  }

  getDocumentsByQuery$<T>(collectionName: string, propertyName: string,
                          comparisonOperator: WhereFilterOp, targetValue: string | boolean): Observable<T[]> {
    return this.db.collection<T>(
      collectionName,
      ref => ref.where(propertyName, comparisonOperator, targetValue)).snapshotChanges().pipe(
      map(actions => actions.map(action => {
        const id = action.payload.doc.id;
        const data: T = action.payload.doc.data() as T;
        data[ 'id' ] = id;
        return data;
      }))
    );
  }

  addDocument<T>(collectionName: string, document: T) {
    const guid: string = Guid.raw();
    return fromPromise(this.db.collection<T>(collectionName).doc(guid).set(document))
      .pipe(
        map(() => {
          const returnDocument: T = document;
          document[ 'id' ] = guid;
          return returnDocument;
        })
      );
  }

  addBatch<T>(collectionName: string, documents: Array<T>) {
    const batch = this.db.firestore.batch();
    const collectionRef = this.db.collection<T>(collectionName);

    documents.forEach((document: T) => {
      const guid: string = Guid.raw();
      const docRef = collectionRef.doc(guid).ref;
      batch.set(docRef, document);
    });

    return fromPromise(batch.commit());
  }

  updateDocument<T>(collectionName: string, document: T, data: any) {
    return this.db.collection<T>(collectionName).doc(document['id']).update(data);
  }

  deleteDocument<T>(collectionName: string, document: T) {
    return this.db.collection<T>(collectionName).doc(document['id']).delete();
  }

}

我知道这项服务可以改进,我会开始这样做,但我想我会为了完整起见将它包括在内。

任何改进建议将不胜感激。

4

1 回答 1

1

一些可能值得考虑的建议:

由于时间表总是在一个组内使用,因此拥有@Selector该结构的项目可能更容易/更整洁。

它仍然可以是一个scheduleGroupId带有schedules. 然后在模板中你只有一个Observable你订阅的,它返回你想要的数据形状。该投影可能更适合 UI,而如果您稍后通过时间表上的 CRUD 操作修补该状态,则保持扁平结构可能会使生活更轻松?

我遇到的问题之一是,即使是简单的组件最终也会变成容器。以 ScheduleListComponent 为例,它需要显示来自相关表的数据。获取此数据取决于在 *ngFor 迭代期间哪个特定的 Schedule 项处于焦点。

我不太清楚你的意思是什么——因为你正在通过 NGXS 初始化钩子发送操作,GetSchedules所以GetScheduleGroups无论如何你都会急切地获取所有东西,对吗?我可能在这里误解了一些东西。

是否有组件SchedulesListItem导致问题?

于 2018-10-18T06:19:47.043 回答