Как связать коллекции Firestore для имитации соединений SQL или WHERE IN - PullRequest
0 голосов
/ 22 мая 2019

У меня есть база данных Firebase Cloud Firestore с 3 коллекциями;Сайты, группы и групповые сайты.Группы могут быть связаны со многими сайтами, отсюда и коллекция GroupSites.Если у меня есть ID группы, я хочу получить связанные сайты через их членство в GroupSites.Данные выглядят так:

Sites:
   - Id: ByBWwnFVXqnJO8FL5n2y
     - SiteName: Penrith
     - Supervisor: Bob
     - Address: zzz site address
   - Id: Hfui74ytBBzUw3OjIg1f
     - SiteName: Keswick
     - Supervisor: Bill
     - Address: yyy site address
   - Id: KKeQen0P3npldFVzt7fG
     - SiteName: Browns Plains
     - Supervisor: Tony
     - Address: xxx site address
Groups:
   - Id: iAX0GE9ZRU0AuxXMBkid
     - GroupName: Group 1
     - isPublic: 0
GroupSites:
   - Id: jxpvUYkopOXNhKisYznC
     - siteId: ByBWwnFVXqnJO8FL5n2y
     - groupId: iAX0GE9ZRU0AuxXMBkid
   - Id: p0jq3clihb0JRjhH5qon
     - siteId: Hfui74ytBBzUw3OjIg1f
     - groupId: iAX0GE9ZRU0AuxXMBkid

Так, например, если бы у меня был идентификатор группы 'iAX0GE9ZRU0AuxXMBkid', я бы хотел получить сайты 'Penrith' и 'Keswick'. В SQL я мог бы легко выполнить что-тонапример:

SELECT [SiteName], [Supervisor] 
FROM Sites 
WHERE Id IN (
   SELECT [siteId] 
   FROM [GroupSites] 
   WHERE groupId = 'iAX0GE9ZRU0AuxXMBkid'
)

... или я мог бы выполнить ВЫБОР ИЗ САЙТОВ, объединенных на [GroupSites].Моя проблема заключается в репликации этого в Firebase.Я могу выбрать из таблицы GroupSites мои критерии GroupId, но что делать с возвращенными результатами, чтобы затем запросить таблицу Sites?

Все примеры, которые я нахожу в Интернете, похоже, относятся к более ранним версиямfirebase - или, возможно, потому что я использую библиотеку AngularFirestoreCollection, которую они не связывают, потому что у меня есть синтаксические ошибки или ошибки «метод не найден» практически во всем, с чем я сталкиваюсь.

Вот мой угловой сервис:

import { Injectable } from '@angular/core';
import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/firestore';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

export interface GroupSite {
  id?: string;
  groupId: string;
  siteId: string;
}

export interface Site {
  id?: string;
  siteName: string;
  supervisor: string;
  address: string;
}

@Injectable({
  providedIn: 'root'
})
export class SiteService {
  private sitesCollection: AngularFirestoreCollection<Site>; 
  private sites: Observable<Site[]>;

  private groupSitesCollection: AngularFirestoreCollection<GroupSite>;
  private groupSites: Observable<GroupSite[]>;

  constructor(private db: AngularFirestore) {
    this.sitesCollection = db.collection<Site>('Site');

    this.sites = this.sitesCollection.snapshotChanges().pipe(
      map(actions => {
        return actions.map(a => {
          const data = a.payload.doc.data();
          const id = a.payload.doc.id;
          return { id, ...data };
        });
      })
    );
  } 

  getSites() {
    return this.sites;
  }

  getSitesByGroup(groupId: string) {

    this.groupSitesCollection = this.db.collection<GroupSite>('GroupSites'), ref => ref.where('groupId', '==', groupId);
    this.groupSites = this.groupSitesCollection.snapshotChanges().pipe(
      map(actions => {
        return actions.map(a => {
          const data = a.payload.doc.data();
          const id = a.payload.doc.id;
          return { id, ...data };  
        });
      })
    ); 

    console.log('groupSites: ', this.groupSites)

    // get Sites referenced in this.groupSites

    return this.sites;
  }
}

оператор console.log () в моем коде возвращает пустой объект, и я понимаю, что это потому, что данные еще не возвращены из firebase, поэтому я подозреваю, что для получения [Sites] потребуетсяв snapshotChanges (). pipe (), но я не могу найти ни одного примера для работы.

Ответы [ 2 ]

0 голосов
/ 22 мая 2019

Коллекции Firestore разрешают вложенные коллекции, вы можете дублировать данные внутри коллекции (при необходимости) с помощью функции firestore, если вам нужно обновить автоматически, например, имя и идентификатор.

Вы можете сохранить динамическийКоллекция, которая напоминает ваш запрос, просто нужно определить логику для каждого события, связанного со схемой.

  • catalogs

    • sites [name, id, supervisor,address, groupId]
    • groups [name, id]
  • relCatalogs (это вы используете для запросов на присоединение)

    • groups / {groupId} / sites [id, name]
  • функции

    • onCreate / update Site -> установить идентификатор и имя вrelCatalog
0 голосов
/ 22 мая 2019

Один запрос не может эффективно включать документы в двух разных коллекциях. Для вашей схемы, поскольку вы включаете документы в две коллекции, вам необходимо выполнить несколько запросов, чтобы иметь возможность прочитать все необходимое.

Вам нужно будет взять результаты запроса groupSitesCollection, выполнить итерацию полученных документов, чтобы получить все поля siteId, и выполнить новые запросы, чтобы получить каждый документ siteId из коллекции Sites.

...