如何使用 firestore 在 angularfire2 中绑定多个查询结果?

How to bind multiple query results in angularfire2 with firestore?

我想按照提议 使用集合来维护某些文档之间的关系(但方法略有修改)。我选择了收集方法,因为随着时间的推移记录属性似乎更具可扩展性。

我的实际数据结构

users
   user1
   user2

companies
   co1
   co2

user_co
   user1
       companies (collection)
           co1
           co2

   user2
       companies (collection)
           co1

但是使用这种方法,我需要进行多次查询才能为特定用户获取所有可用的公司,因为我们无法执行 "IN" 子句。

所以我需要分两步检索数据:

  1. 检索 user_co/{user}/companies
  2. 中有权访问的公司用户列表
  3. /companies/{id}
  4. 中检索实际公司

为什么需要 2 个步骤?因为我不想将所有公司的读取权限授予所有用户,查询 /companies 会触发访问错误。

所以我对如何检索从多个调用中检索到的单个可绑定文档列表感到困惑?

我的组件中显示了 2 个项目,但字段值没有显示。我在检索 /company 文件的方式上确实做错了。

如有任何帮助,我们将不胜感激。

MyService.ts

interface Company {
    Name: string;
    Owner: any;
    id?: any;
    time?: any;
    creationTime?: any;
}

interface MyCompany {
    id?: any;
    Name: string;
}

@Injectable()
export class CompanyService {

    companiesCollection: AngularFirestoreCollection<Company>;
    myCompaniesCollection: AngularFirestoreCollection<MyCompany>;
    myCompanies;

    constructor(private afs: AngularFirestore, private ats: AuthService) {

        this.myCompaniesCollection = this.afs.collection('user_co').doc(this.ats.currentUserId).collection('companies');
        this.myCompanies = this.myCompaniesCollection.snapshotChanges().map(actions => {
            return actions.map(a => {
                // What is the good way to retrieve /companies data from here?
                return this.afs.firestore.collection("companies").doc(a.payload.doc.id).get().then(doc => {
                    return { id: doc.id, ...doc.data() }
                }).catch(error => {
                    console.log("Error reading company document:", error);
                });
                // Original example that return data from /user_co
                //return { id: a.payload.doc.id, ...a.payload.doc.data() }
            })
        });
    }

    getData() {
        return this.myCompanies;
    }
}

将 angularfire2 5.0.0-rc.3 与 firebase 4.5.2 结合使用

我终于改变了将数据存储到 Firestore 的方式。

如前所述 here 和许多与 NoSQL 相关的文档中,非规范化是避免 "join like" 和多个查询的方法。

Using denormalization one can group all data that is needed to process a query in one place. This often means that for different query flows the same data will be accessed in different combinations. Hence we need to duplicate data, which increases total data volume.

这样,我可以简单地检索 /users/{user}/companies 并获取有关用户所属公司的所有相关信息。并且无论如何都不需要能够访问所有用户的所有公司信息(设置、用户等)。

新数据结构

/users/{user}
    user_name
    /companies/{company}
       company_name

/companies/{company}
    name
    /admins/{user}
    /users/{user}
        user_name

允许管理员 invite/add 用户访问公司的安全规则

match /users/{usr}/companies/{co} {
    // Only visible to the actual user
    allow read: if request.auth.uid == usr;

    // Current user can opt-out of company
    allow delete: if request.auth.uid == usr ||
        // Company admin can add or drop-out a user
        exists(/databases/$(db)/documents/companies/$(co)/admins/$(request.auth.uid));

    // Company admin can add or drop-out a user
    allow create, update: if exists(/databases/$(db)/documents/companies/$(co)/admins/$(request.auth.uid));
}

match /companies/{co} {
    // Company accessible for members and admins only
    allow read: if
        exists(/databases/$(db)/documents/companies/$(co)/members/$(request.auth.uid)) || 
            exists(/databases/$(db)/documents/companies/$(co)/admins/$(request.auth.uid));

    match /admins/{usr} {
        // allow company creation if it does not exists
        allow create: if exists(/databases/$(db)/documents/companies/$(co)) == false
        // updates allowed for admins
        allow update, delete: if exists(/databases/$(db)/documents/companies/$(co)/admins/$(request.auth.uid));
    }
    match /users/{usr} {
      // writes allowed for admins
      allow write: if exists(/databases/$(db)/documents/companies/$(co)/admins/$(request.auth.uid));
    }
}

对方

更新/companies/{company}/[name]时,我还需要通过/companies/{company}/users检索属于该公司的所有用户,然后更新/users/{user}/companies/{company}中的所有文档。这可以在单个 transaction.

内完成