从一个已知的子集合中检索所有文档

Retrieve all documents from just one known subcollection

我有这个 Firestore 结构:

Category: {
    document1a: {
        name : "reptiles"
        animalsubcollection: {
            Document1b: {
                name: "snake"
                color: "white"
            }
            Document2b: {
                name: "lizard"
                color: "black"
            }
    document2a: {
        name : "mammals"
        animalsubcollection: {
            Document1b: {
                name: "monkey"
                color: "brown"
            }
            Document2b: {
                name: "cat"
                color: "white"
            }

我需要在单个页面中列出该信息,按如下类别分类:

爬行动物:

哺乳动物:

就像上面的例子一样,我总是只有一个已知的子集合,叫做 animalsubcollection

如何在 Angular 5 中使用 AngularFire2 实现此目的?

如果它不是此类信息的最佳 firestore 模型,我可以根据需要进行更改。我接受其他人的建议以达到相同的结果。

我建议您规范化您的数据结构。您可以遵循以下模式:https://redux.js.org/recipes/structuring-reducers/normalizing-state-shape

在您的数据结构的一个节点中,存储您拥有的所有 "animals"。在其他情况下,存储所有 "animal categories"。另一方面,存储它们之间的关系,为每个类别关联动物 'key'.

{
    animals: {
        snake: { color: 'white '},
        lizard: { color: 'black' },
        monkey: { color: 'brown '}
    },
    categories: {
        reptiles: { description: 'something here about reptiles'},
        mammals:  { description: 'something here about mammals'}
    },
    animals_categories: {
        reptiles: ['snake', 'lizard'],
        mammals: ['monkey']
    }

}

因此您将能够查询类别,然后使用每个类别的动物键,您将能够获取动物的详细信息。 尽管我提供的 link 来自 Redux 的文档,但此模式并未绑定到 Redux。这是基于文档的这种数据结构的常见用法。

假设您有一个有效的 JSON 数组(您发布的数组无效)您可以使用 Angular 以非常简单的方式完成此操作。

您可以在 angular 应用中使用下划线轻松将其存档。

groupedSeriesNames = []
groupedSeries = []



categories =  Category: {
        document1a: {
            name : "reptiles"
            animalsubcollection: {
                Document1b: {
                    name: "snake"
                    color: "white"
                }
                Document2b: {
                    name: "lizard"
                    color: "black"
                }
        document2a: {
            name : "mammals"
            animalsubcollection: {
                Document1b: {
                    name: "monkey"
                    color: "brown"
                }
                Document2b: {
                    name: "cat"
                    color: "white"
                }
           .
           .
           .

更好的数据结构示例:

{
        type: "reptiles",       
        name: "snake",
        color: "white"


    },
    {
        type: "reptiles",       
        name: "snake",
        color: "white"
    },
    {
        type: "mammals",        
        name: "snake",
        color: "white"
    }
}

{
        name: "reptiles",
        animalsubcollection: {
            Document1b: {
                name: "snake",
                color: "white"
            }
        }
    },
    {
        name: "mammals",
        animalsubcollection: {
            Document1b: {
                name: "leion",
                color: "white"
            }
        }
    },
    {
        name: "mammals",
        animalsubcollection: {
            Document1b: {
                name: "papa",
                color: "white"
            }
        }
    }
this.groupedTypes = _.groupBy(this.categories, category=>category.name);
this.groupedSeriesNames = Object.keys(this.groupedSeries)

certificate.serie 将成为他们的关键,您可以将 certificate.serie 更改为任何其他 属性,例如 iden 或任何您需要的

你的html

<ul class="cert-result">
    <li *ngFor="let key of groupedSeriesNames">
      <table *ngFor="let category of groupedSeries[key]">
        <tr>
          <th>Name</th>
          <th>Color</th>
        </tr>
        <tr>
          <td>{{category.color}}</td>
          <td>{{category.name}}</td>
        </tr>
      </table>
    </li>
  </ul>

不使用下划线的代码(假设 json 结构正确)

function formatedCerts() {
      return categories.reduce((prev, now) => {
        if (!prev[now.name]) {
          prev[now.name] = [];
        }

        prev[now.name].push(now);
        return prev;
      }, {});
}

感谢大家的建议,但最初的提议不是规范化原始数据库模型,而是使用原始模型找到一个简单的解决方案。

我知道有时候,创建 2 或 3 个新的规范化集合并解决问题会更容易。另一方面,如果有可能创建子集合,则需要存在一种以 Angular em RxJS 方式查询其数据的方法。

所以,经过 2 或 3 天的研究,我找到了一种方法:

//necessary imports
import { Observable } from 'rxjs/observable';
import { combineLatest } from 'rxjs/observable/combineLatest';
import 'rxjs/add/operator/mergeMap';

// the observable for animals category collection
this.animals = this.afs
  .collection('Category')
  .snapshotChanges()
  .map(arr => {
    return arr.map(snap => {
      const categ = { id: snap.payload.doc.id, ...snap.payload.doc.data() };

      // the animalsubcollection, using the previous value as parameter
      return this.afs
        .collection(`Category/${categ.id}/animalsubcollection`)
        .valueChanges()
        .map(animalsub => {
          return { ...categ, animalSubs: animalsub };
        });
    });
  })
  .mergeMap(result => combineLatest(result));
  //thats the trick. Combine 2 observables into a new one.

在视图中:

<ion-card *ngFor="let animal of animals | async">
<p *ngFor="let as of animal.animalSubs">
     {{as.name}} - {{as.color}}
</p>

希望对大家有所帮助