从一个已知的子集合中检索所有文档
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>
希望对大家有所帮助
我有这个 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>
希望对大家有所帮助