用可观察的方式在两个字段上存储多个查询

时间:2019-09-15 16:50:04

标签: angular google-cloud-firestore

我正在使用Angular和Firestore。

我想在两个字段上对Firestore数据库执行多次查询。现在,可以结合使用WHERE语句了。 我的想法是合并值,然后将请求发送到数据库。例如,我想找回所有城市为洛杉矶,旧金山,纽约且“星级评分”为5、4的邮局。

所以我必须查询6种可能的组合:

Where city = Los Angeles
Where Stars = 5

...然后进行下一个查询

Where city = Los Angeles
Where stars = 4

...然后进行下一个查询

Where city = San Francisco
Where Stars = 5

...然后进行下一个查询

Where city = San Francisco
Where Stars = 4

等等。

我知道如何使用For语句来处理一个字段和一个值,如下面的代码所示,但是我不知道如何组合它们(将组合组合成多个查询) ,然后等待所有对象(带有可观察对象或主题)执行以将它们组合在结果数组中。我在Stack上找到了两个答案,但没人能真正帮助我做出一个好的决定。

这一个,但仅在一个字段上,不可观察 Multiple Firestore queries, single promise / callback

另外一个 Firestore multiple range query 谁想到了“对查询中的一个字段执行过滤,而对客户端代码中的另一个字段执行过滤”。 如果您的结果很少,那么此解决方案是很好的选择,但是如果结果很多,则可以减慢该过程,并取回我们不需要的数据。

export class AnnoncesListComponent implements OnInit {

  queryParams: { departement:string, secteurAct:string };
  subscriptionChange:Subscription;
  annoncesSubscription:Subscription;
  departementGet: any;
  secteurActGet: any;
  annonceQuery: Annonce[];
  isFetchingData:boolean = false;

  constructor( 
    private activeRoute : ActivatedRoute,
    private annnonceService: AnnoncesService 
    ) { }

  ngOnInit() {
//Get QUERYPARAMS FROM THE URL
   this.departementGet = decodeURIComponent(this.activeRoute.snapshot.queryParams['departement']);
   this.secteurActGet =  decodeURIComponent(this.activeRoute.snapshot.queryParams['secteurActivite']);
   this.departementGet = this.departementGet.split('_B2-');
   this.secteurActGet = this.secteurActGet.split('_B2-');

//FOR - TO QUERIES ALL THE DATA NEEDED - FIRST QUERY
   for (var i = 0; i < this.secteurActGet.length; i++) {
    this.annoncesSubscription = this.annnonceService.getAnnonces('secteurActivite', this.secteurActGet[i])
    .subscribe( responseData => {
      this.isFetchingData = false
        this.annonceQuery = responseData.map(item => {
          return {
            id : item.payload.doc.id,
            secteurAct : item.payload.doc.get('secteurActivite'),
            departement : item.payload.doc.get('departement'),
            region : item.payload.doc.get('region'),
            description : item.payload.doc.get('description'),
            infosClefs : item.payload.doc.get('name'),
          } as Annonce;
        })
        console.log(this.annonceQuery);
    });

//FOR - TO QUERIES ALL THE DATA NEEDED - SECOND QUERY
   for (var i = 0; i < this.departementGet.length; i++) {
    this.annoncesSubscription = this.annnonceService.getAnnonces('secteurActivite', this.departementGet[i])
    .subscribe( responseData => {
      this.isFetchingData = false
        this.annonceQuery = responseData.map(item => {
          return {
            id : item.payload.doc.id,
            secteurAct : item.payload.doc.get('secteurActivite'),
            departement : item.payload.doc.get('departement'),
            region : item.payload.doc.get('region'),
            description : item.payload.doc.get('description'),
            infosClefs : item.payload.doc.get('name'),
          } as Annonce;
        })
        console.log(this.annonceQuery);
    });
};

我的结果是两个没有组合的分离数据,并且每次迭代都创建一个可观察的数据。

2 个答案:

答案 0 :(得分:0)

我相信使用rxjs / forkJoin处理多个并行请求是一种好方法。

ForkJoin接受可观察变量数组作为其第一个参数,并返回一个可观察变量,一旦其所有传递的可观察变量都完成,该观察变量就会发出。

我已经将您的代码重构为易于阅读的代码,并且利用forkJoin并行处理部门和部门,然后输出每个结果数据的数组。

如果您正在处理的数据量很大,我什至建议您看一下WebWorkers,以便将cpu密集型操作拆分为多个线程并避免阻塞主线程。

    // map array of departments into an array of Observables
    const departmentsRequests = this.departementGet.map((departement) => {
        return this.annnonceService.getAnnonces('departement', departement);
    });

    const secteurActiviteRequests = this.secteurActGet.map((secteur) => {
        return this.annnonceService.getAnnonces('secteurActivite', secteur);
    });

    // forkJoin takes all Observables and emits once to its subscription
    this.annoncesSubscription = forkJoin([
        forkJoin(departmentsRequests),
        forkJoin(secteurActiviteRequests),
    ]).subscribe(([departaments, secteurs]) => {
        this.isFetchingData = false;

        // all data has been loaded in parallel from firestore, handle it here
    });

答案 1 :(得分:0)

服务中获取数据的功能就是这个:

 getAnnonces(champ, valeur){
        return this.firestore.collection('annonce', ref => ref.where(champ, '==', valeur)).snapshotChanges();
      }

我让你编码,但是当我尝试输出结果时:

 // forkJoin takes all Observables and emits once to its subscription
      this.annoncesSubscription = forkJoin([
          forkJoin(departmentsRequests),
          forkJoin(secteurActiviteRequests),
      ]).subscribe(([departements, secteurs]) => {
          this.isFetchingData = false;
          // all data has been loaded in parallel from firestore, handle it here
          console.log(departements);
      });

没有结果。我尝试使用.get()而不是.snapshotChanges(),但他给了我[QuerySnapshot]