如何从 FirebaseListObservable 映射和减少子值 [英] How to map and reduce child values from FirebaseListObservable

查看:18
本文介绍了如何从 FirebaseListObservable 映射和减少子值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试总结考试成绩,我的数据看起来像这样

 { 测试结果:{ 富:{foo1: x},{foo2: y}},{ 酒吧:{bar1: z}

'foo' 和 'bar' 是有意义的问题子类别,子节点保存 questionID 和相应的分数.我需要总结按类别排序的分数.我这样查询列表

let res = this._dbref.database.list('/bmzi-answers',{询问: {orderByKey:真,等于:id}})

并用 {{ res | 显示结果异步 |json }} 告诉我,查询有效.我得到类似的东西

[{"cat1":3, "cat2":3, "cat3":3, "$key":"cat"}]

如何减少组件逻辑中的值,以获得标记为 cat* 的所有问题的总和?

我了解过滤器/映射/缩减等概念,但我是 Reactive Javascript、Angular2 和 AngularFire 的新手.

请提前帮助并感谢您!

所有孩子都有 cat 前缀,这是域/问卷的一部分.这段代码

 let res = this.dbRef.database.list(`/bmzi-answers/${id}`).do((array) => { console.log(JSON.stringify(array)); }).map((数组) => 数组.reduce((acc, element) => acc + element.$value, 0))让分数 = res.subscribe(sum => {console.log("分数:" + sum)});返回分数;

产生这个控制台输出,第一次被调用:

<预><代码>[{ "$key": "cat1", "$value": 3 },{ "$key": "cat2", "$value": 3 },{ "$key": "cat3", "$value": 3 }]得分:[对象对象]

第二次:

<代码>[]分数:未定义[{"$value":3,"$key":"fitges1"}]分数:未定义[{"$value":3,"$key":"fitges1"},{"$value":3,"$key":"fitges2"}]分数:未定义[{"$value":3,"$key":"fitges1"},{"$value":3,"$key":"fitges2"},{"$value":3,"$key":fitges3"}]分数:未定义

解决方案

您的示例输出表明以下数据:

<代码>{bmzi-答案":{猫": {猫1":3,猫2":3,猫3":3}}}

您的查询使用 orderByKeyequalTo 来获取发出数组的列表 observable.如果键存在,查询将只返回一个包含单个对象的数组.将键合并到查询路径中会更简单,如下所示:

let res = this._dbref.database.list(`/bmzi-answers/${id}`);

此查询返回的 observable 将是一个包含键的子项的数组(以 AngularFire 方式表示):

<预><代码>[{ "$key": "cat1", "$value": 3 },{ "$key": "cat2", "$value": 3 },{ "$key": "cat3", "$value": 3 }]

RxJS map 运算符可用于将发出的数组转换为另一个值,并且可以使用您声明的 Array.proptype 函数执行转换熟悉:

let id = "cat";let regExp = new RegExp(`${id}\\d+`);让 res = this._dbref.database.list(`/bmzi-answers/${id}`).map((数组) => 数组.filter((element) => regExp.test(element.$key)).reduce((acc, element) => acc + element.$value, 0));

如果所有孩子都有 cat 前缀,则不需要 filter,但您的问题并不清楚是否是这种情况.

I am trying to sum up test scores, my data looks like this

   { testResult: 
      { foo:
         {foo1: x},
         {foo2: y}
      },
      { bar:
         {bar1: z}

'foo' and 'bar' are meaningful subcategories of questions, child-nodes hold questionIDs and corresponding scores. I need to sum up scores ordered by categories. I query the list like this

let res = this._dbref.database.list('/bmzi-answers',{
      query: {
        orderByKey: true,
        equalTo: id
      }
    })

and displaying the result with {{ res | async | json }} shows me, that the query works. I get something like

[{"cat1":3, "cat2":3, "cat3":3, "$key":"cat"}]

How can I reduce the values in my component logic, to get the sum of all questions labeled cat* ?

I understand concepts like filter / map / reduce, but I am new to Reactive Javascript, Angular2 and AngularFire.

Please help and thank you in advance!

Edit: All children have the cat prefix, this is part of the domain / the questionnaire. This code

  let res = this.dbRef.database.list(`/bmzi-answers/${id}`)
                  .do((array) => { console.log(JSON.stringify(array)); })
                  .map((array) => array
                      .reduce((acc, element) => acc + element.$value, 0)
            )
  let score = res.subscribe(sum => {
                  console.log("score: " + sum)
              });
  return score;

produces this console output, the first time it's called:

[
    { "$key": "cat1", "$value": 3 },
    { "$key": "cat2", "$value": 3 },
    { "$key": "cat3", "$value": 3 }
]
score: [object Object]

and the second time this:

[]  
score: undefined  
[{"$value":3,"$key":"fitges1"}]
score: undefined  
[{"$value":3,"$key":"fitges1"},{"$value":3,"$key":"fitges2"}]
score: undefined 
[{"$value":3,"$key":"fitges1"},{"$value":3,"$key":"fitges2"},{"$value":3,"$key":"fitges3"}]  
score: undefined 

解决方案

Your example output suggests the following data:

{
    "bmzi-answers": {
        "cat": {
            "cat1": 3,
            "cat2": 3,
            "cat3": 3
        }
    }
}

Your query uses orderByKey and equalTo to obtain a list observable that emits an array. Provided the key exists, the query will only ever return an array containing a single object. It would be simpler to incorporate the key in the query's path, like this:

let res = this._dbref.database.list(`/bmzi-answers/${id}`);

The observable returned by this query will be an array containing the key's children (represented in the AngularFire way):

[
    { "$key": "cat1", "$value": 3 },
    { "$key": "cat2", "$value": 3 },
    { "$key": "cat3", "$value": 3 }
]

The RxJS map operator can be used to transform the emitted array to another value and the transformation can be performed using the Array.proptype functions with which you state you are familiar:

let id = "cat";
let regExp = new RegExp(`${id}\\d+`);
let res = this._dbref.database
    .list(`/bmzi-answers/${id}`)
    .map((array) => array
        .filter((element) => regExp.test(element.$key))
        .reduce((acc, element) => acc + element.$value, 0)
    );

If all children have the cat prefix, the filter is not required, but your question doesn't make clear whether or not that's the case.

这篇关于如何从 FirebaseListObservable 映射和减少子值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆