我有这个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实现这一目标?
如果它不是此类信息的最佳防火墙模型,我可以在必要时进行更改。我接受其他建议来达到同样的结果。
答案 0 :(得分:2)
我建议你来确定你的数据结构。您可以遵循以下模式:https://redux.js.org/recipes/structuring-reducers/normalizing-state-shape
在数据结构的一个节点中,存储所有"动物"你有。在其他情况下,存储所有"动物类别"。在另一方面,存储它们之间的关系,为每个类别关联动物的关键'。
{
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']
}
}
因此,您可以查询类别,然后查看动物'每个类别的键,您将能够获取动物的详细信息。 虽然我提供的链接来自Redux'文档,这种模式不受Redux的约束。这是基于文档的这种数据结构中的常见用法。
答案 1 :(得分:1)
感谢大家的建议,但最初的提案并未规范原始数据库模型,而是使用原始模型找到一个简单的解决方案。
我知道有时候,只需简单地创建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>
我希望它有助于某人
答案 2 :(得分:0)
假设您有一个有效的JSON数组(您发布的那个数组无效)您可以使用Angular以一种非常简单的方式完成此操作。
您可以使用角应用中的下划线轻松归档此内容。
how to use underscore.js library in angular 2
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"
}
}
OR
{
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;
}, {});
}