如何映射和减少 Firebase List Observable 中的 child 值
How to map and reduce child values from FirebaseListObservable
我正在尝试总结考试成绩,我的数据是这样的
{ testResult:
{ foo:
{foo1: x},
{foo2: y}
},
{ bar:
{bar1: z}
'foo' 和 'bar' 是有意义的问题子类别,child-nodes 包含问题 ID 和相应的分数。我需要总结按类别排序的分数。我这样查询列表
let res = this._dbref.database.list('/bmzi-answers',{
query: {
orderByKey: true,
equalTo: id
}
})
并用 {{ res | async | json }}
显示结果告诉我,查询有效。我得到类似
的东西
[{"cat1":3, "cat2":3, "cat3":3, "$key":"cat"}]
如何减少组件逻辑中的值,以获得所有标记为 cat* 的问题的总和?
我了解 filter/map/reduce 等概念,但我是 Reactive Javascript、Angular2 和 AngularFire 的新手。
请提前帮忙,谢谢!
编辑:
所有 children 都有 cat 前缀,这是域/问卷的一部分。此代码
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;
第一次调用时产生此控制台输出:
[
{ "$key": "cat1", "$value": 3 },
{ "$key": "cat2", "$value": 3 },
{ "$key": "cat3", "$value": 3 }
]
score: [object Object]
这是第二次:
[]
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
您的示例输出建议以下数据:
{
"bmzi-answers": {
"cat": {
"cat1": 3,
"cat2": 3,
"cat3": 3
}
}
}
您的查询使用 orderByKey
和 equalTo
来获取发出数组的可观察列表。如果键存在,查询只会 return 一个包含单个 object 的数组。将键合并到查询路径中会更简单,如下所示:
let res = this._dbref.database.list(`/bmzi-answers/${id}`);
此查询所观察到的 return 将是一个包含键 children 的数组(以 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+`);
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)
);
如果所有 children 都有 cat
前缀,则不需要 filter
,但您的问题并不清楚是否是这种情况。
流发出数据。一个可观察对象是一个流。
例如:
let stream = Rx.Observable.from([3,6,9])
此代码创建一个可观察流,它发出 3 然后 6 然后 9
现在假设我们想将这些值加倍:
let stream = Rx.Observable.from([3,6,9]).map((value) => {return value*2})
现在流发出 6、12、18。
我们终于可以做到了:
let stream1 = Rx.Observable.from([3,6,9])
let stream2 = stream1.map((value) => {return value*2})
现在我们可以订阅 stream1 或 stream2 或两者。
PS 一个 .reduce()
函数也可用,与 es5 Array.reduce
函数一样。您可以对流执行与对数组相同的操作。
数组是内存序列。流是随时间变化的序列。
这就是我们可以轻松地将数组转换为流的原因。我们可以在每次发射之间设置间隔。等等
我正在尝试总结考试成绩,我的数据是这样的
{ testResult:
{ foo:
{foo1: x},
{foo2: y}
},
{ bar:
{bar1: z}
'foo' 和 'bar' 是有意义的问题子类别,child-nodes 包含问题 ID 和相应的分数。我需要总结按类别排序的分数。我这样查询列表
let res = this._dbref.database.list('/bmzi-answers',{
query: {
orderByKey: true,
equalTo: id
}
})
并用 {{ res | async | json }}
显示结果告诉我,查询有效。我得到类似
[{"cat1":3, "cat2":3, "cat3":3, "$key":"cat"}]
如何减少组件逻辑中的值,以获得所有标记为 cat* 的问题的总和?
我了解 filter/map/reduce 等概念,但我是 Reactive Javascript、Angular2 和 AngularFire 的新手。
请提前帮忙,谢谢!
编辑: 所有 children 都有 cat 前缀,这是域/问卷的一部分。此代码
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;
第一次调用时产生此控制台输出:
[
{ "$key": "cat1", "$value": 3 },
{ "$key": "cat2", "$value": 3 },
{ "$key": "cat3", "$value": 3 }
]
score: [object Object]
这是第二次:
[]
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
您的示例输出建议以下数据:
{
"bmzi-answers": {
"cat": {
"cat1": 3,
"cat2": 3,
"cat3": 3
}
}
}
您的查询使用 orderByKey
和 equalTo
来获取发出数组的可观察列表。如果键存在,查询只会 return 一个包含单个 object 的数组。将键合并到查询路径中会更简单,如下所示:
let res = this._dbref.database.list(`/bmzi-answers/${id}`);
此查询所观察到的 return 将是一个包含键 children 的数组(以 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+`);
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)
);
如果所有 children 都有 cat
前缀,则不需要 filter
,但您的问题并不清楚是否是这种情况。
流发出数据。一个可观察对象是一个流。
例如:
let stream = Rx.Observable.from([3,6,9])
此代码创建一个可观察流,它发出 3 然后 6 然后 9
现在假设我们想将这些值加倍:
let stream = Rx.Observable.from([3,6,9]).map((value) => {return value*2})
现在流发出 6、12、18。
我们终于可以做到了:
let stream1 = Rx.Observable.from([3,6,9])
let stream2 = stream1.map((value) => {return value*2})
现在我们可以订阅 stream1 或 stream2 或两者。
PS 一个 .reduce()
函数也可用,与 es5 Array.reduce
函数一样。您可以对流执行与对数组相同的操作。
数组是内存序列。流是随时间变化的序列。
这就是我们可以轻松地将数组转换为流的原因。我们可以在每次发射之间设置间隔。等等