从一个已知的子集合

时间:2018-05-18 17:44:29

标签: angular firebase ionic3 google-cloud-firestore angularfire2

我有这个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"
            }

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

爬行动物:

  • Snake:White
  • 蜥蜴:黑色

哺乳动物

  • 猴子:布朗
  • 猫:白色

与上面的例子一样,我总是只有一个名为animalsubcollection的已知子集。

如何在Angular 5中使用AngularFire2实现这一目标?

如果它不是此类信息的最佳防火墙模型,我可以在必要时进行更改。我接受其他建议来达到同样的结果。

3 个答案:

答案 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;
      }, {});
}