Firebase是否支持分组计数?
我想计算按值分组的特定键。
我的数据结构示例:
"playbackPosition" : {
"-JZ2c7v-imQXaEx2c4Cs" : {
"data" : "0"
},
"-JZ2cDta73UGAgwIOejL" : {
"data" : "25"
},
"-JZ2cJutDZu-7quLpLI2" : {
"data" : "50"
},
"-JZ2cO-Me0nGK5XLTwd-" : {
"data" : "75"
},
"-JZ2cSh-XnstYxbE_Zad" : {
"data" : "100"
},
"-JZ2cWxya0-kmTPCze4u" : {
"data" : "0"
},
"-JZ2c_wX-ODv43TKXkNG" : {
"data" : "25"
}
}
基于data
键的必需结果:
0 => 2
25 => 2
50 => 1
75 => 1
100 => 1
当然,我必须考虑它会有成千上万的孩子,而不仅仅是7 ......
提前致谢!
修改
更深入地解释应用程序和我们想要解决的问题。
我们有在不同网站上运行的视频脚本,每个视频会话(用户会话)都会发送事件和数据,您可以在此处查看示例,查看网络标签 - https://secure.bwebi.co/videostir/regular.html
我们的目标是收集这些数据并创建一个包含少量图表和图形的分析实时仪表板。
您可以看到我们当前的数据结构here
我们需要的图表示例:
完成率
常规 - 条形图显示每个剪辑持续时间预定义时段的总观看次数
过滤器 - 日期(开始/结束),唯一/全部,所有网址/特定网址(嵌入),所有配置/特定配置/忽略静默。
X轴 - 组0-25,25-50,50-75,75-99,100
Y轴 - 视图数
每日观看次数(完成率)
常规 - 显示每个持续时间每天观看次数的多行图表
过滤器 - 日期(开始/结束),唯一/全部,所有网址/特定网址(嵌入),所有配置/特定配置/忽略静默。
X轴 - 以天为单位的时间
Y轴 - 视图数量
行:
每日总观看次数
每日观看次数为100%
持续时间为75-99%的每日观看次数
每日观看时间为50-75%
每日观看时间为25-50%
每日观看次数为0-25%
希望现在更清楚了!
答案 0 :(得分:9)
Group by是一个SQL函数。 SQL无法执行实时数据的原因是因为这种方法无法扩展。 Mongo提供了类似的功能,但又一次it doesn't scale。您可能会注意到Firebase不提供此类查询功能的原因。
如果你提供了一些关于你在这里实际尝试完成的内容,应用规则是什么以及你已经排除了什么方法的背景,而不仅仅是你的预设,那将是非常有帮助的。分组的解决方案。可能还有其他可能更好的选择。请参阅XY problem。
以下是通过对您的用例做出全面假设而得出的几个通用替代方案。
这是最具扩展性的解决方案。存储您的数据如下:
/playbacks/$id/<playback data>
/group_totals/$group/<count>
写入播放时,还要更新相应组的计数:
var fb = new Firebase(URL);
function addPlayback(rec) {
var ref = fb.child('playbacks').push(rec, function(err) {
if( err ) throw err;
incrementCount(rec.data);
});
}
function incrementCount(count) {
fb.child('group_totals/' + count).transaction(function(currentVal) {
return (currentVal||0)+1;
});
}
现在,当您想要获得组的总数时,您只需在group_totals / $ group中查找值即可。同样,您可以存储属于每个组的记录的ID,并使用index仅抓取给定组的记录。
更简单的方法是根据组/数据值为每条记录赋予优先级。
var fb = new Firebase(URL);
function addPlayback(rec) {
rec['.priority'] = rec.data;
var ref = fb.child('playbacks').push(rec, function(err) {
if( err ) throw err;
});
}
现在获取给定组的一组记录:
var fb = new Firebase(URL);
function getGroup(groupValue, callback) {
fb.child('playbackPosition').startAt(groupValue).endAt(groupValue).once('value', callback);
}
function logGroupCount(groupValue, callback) {
getGroup(groupValue, function(snap) {
console.log('there are ' + snap.numChildren() + ' items in group ' +groupValue);
});
}
答案 1 :(得分:0)
一个不是专业的程序员,我只是在学习。 这是我想对查询结果进行分组时想出的一段代码:
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
progressBar.setVisibility(View.VISIBLE);
tv_info.setText("Please wait ... ");
Query query = collectionRef.orderBy("timestamp", Query.Direction.DESCENDING);
query.get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
@Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
String dataInfo = "";
int arrayLength = 1;
List <String> UsedNames = new ArrayList<String>();
String someName = "...";
String oneRow = "";
int orderNumber = -1;
int count = 0;
for (QueryDocumentSnapshot documentSnapshot : queryDocumentSnapshots) {
OneRecord oneRecord = documentSnapshot.toObject(OneRecord.class);
someName = oneRecord.getSomeName();
if (UsedNames.contains(someName)) {
// Log.i("test" , "Array Contains ");
} else {
orderNumber += 1;
UsedNames.add(someName);
}
}
List list = queryDocumentSnapshots.toObjects(OneRecord.class);
for (String someString : UsedNames) {
int counter = 0;
for (int i = 0; i < list.size(); i++) {
OneRecord oneRecord = (OneRecord) list.get(i);
String name = oneRecord.getName();
if (someString.equals(name)) {
counter += 1;
}
}
Log.i("test" , "Array: " + someString + " : " + counter);
count = count +1;
dataInfo = dataInfo + someString + " : " + counter + "\n";
}
Log.i("test" , "Used length: " + UsedNames.size());
progressBar.setVisibility(View.GONE);
tv_info.setText(dataInfo);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
progressBar.setVisibility(View.GONE);
tv_info.setText("Could not query last records: " + e.getMessage());
}
});
}
});
不幸的是我没有弄清楚如何按降序或升序对它们进行排序