Firebase 实时数据库按状态值计算活跃用户数

Posted

技术标签:

【中文标题】Firebase 实时数据库按状态值计算活跃用户数【英文标题】:Firebase Realtime database count active users by status value 【发布时间】:2022-01-09 01:29:22 【问题描述】:

我有一项服务可以检测用户在 firebase 中在线、离开和离线时的存在情况。

presence.service.ts

import  Injectable  from "@angular/core";
import  AngularFireAuth  from "@angular/fire/auth";
import  AngularFireDatabase  from "@angular/fire/database";
import * as firebase from "firebase/app";
import  tap, map, switchMap, first  from "rxjs/operators";
import  of  from "rxjs";
import  SuperUserService  from "./../services/superuser.service";

@Injectable(
  providedIn: "root",
)
export class PresenceService 
  constructor(
    private afAuth: AngularFireAuth,
    private db: AngularFireDatabase,
    private superuser: SuperUserService
  ) 
    console.log("Verificação de status em execução");
    this.setName();
    this.updateOnUser().subscribe();
    this.updateOnDisconnect().subscribe();
    this.updateOnAway();
  

  getPresence(uid: string) 
    return this.db.object(`status/$uid`).valueChanges();
  

  getUser() 
    return this.afAuth.authState.pipe(first()).toPromise();
  

  async setPresence(status: string) 
    const user = await this.getUser();
    if (user) 
      return this.db.object(`status/$user.uid`).update(
        status,
        timestamp: this.timestamp,
      );
    
  

  async setName() 
    const user = await this.getUser();
    if (user) 
      return this.db.object(`status/$user.uid`).update(
        nome: this.superuser.user.displayName,
      );
    
  

  get timestamp() 
    return firebase.database.ServerValue.TIMESTAMP;
  

  updateOnUser() 
    const connection = this.db
      .object(".info/connected")
      .valueChanges()
      .pipe(map((connected) => (connected ? "online" : "offline")));

    return this.afAuth.authState.pipe(
      switchMap((user) => (user ? connection : of("offline"))),
      tap((status) => this.setPresence(status))
    );
  

  updateOnDisconnect() 
    return this.afAuth.authState.pipe(
      tap((user) => 
        if (user) 
          return this.db
            .object(`status/$user.uid`)
            .query.ref.onDisconnect()
            .update(
              status: "offline",
              timestamp: this.timestamp,
            );
        
      )
    );
  

  async signOut() 
    await this.setPresence("offline");
    await this.afAuth.signOut();
  

  
  updateOnAway() 
    document.onvisibilitychange = (e) => 
      if (document.visibilityState === "hidden") 
        this.setPresence("away");
       else 
        this.setPresence("online");
      
    ;
  

Firebase 路径

考虑到这一点,我想要实现一种方法来显示有多少用户是活跃的(在线和离开例如:15 个活跃用户

我试过这个,但它只会让我知道是否存在

ref.child("status").orderByChild("status").equalTo("online")
.once("value",snapshot => 
if (snapshot.exists())
  // if exist

);

【问题讨论】:

【参考方案1】:

如果你想用你当前的数据结构显示在线用户的数量,你可以保持与之前相同的查询,然后use snapshot.numChildren() 来确定它返回的在线用户的数量。


如果您想使用当前数据结构显示在线和离线用户的计数,您可以:

对离线用户使用第二个查询,并使用与上述相同的方法来获取计数。

status 字段上使用不带条件的单次读取,然后计算应用程序代码中的各个节点:

ref.child("status")
.once("value",snapshot => 
  let onlineCount=0, offlineCount=0;
  snapshot.forEach((user) => 
    const status = user.child("status").val();
    if (status === "online) onlineCount++
    else if (status === "offline) offlineCount++
    else console.error(`Unexpected status '$status' for user $user.key`);
  )
  console.log(`Online: $onlineCount, Offline: $offlineCount`);
);

如果您阅读所有这些用户配置文件只是为了在您的应用中显示两个计数器,那么您会为您自己和您的用户浪费相当多的带宽(因此也就是金钱)。考虑将您希望在数据库本身中显示的实际计数存储起来,并在每个用户在线/离线时在 Cloud Functions 等工具中更新它们。

【讨论】:

以上是关于Firebase 实时数据库按状态值计算活跃用户数的主要内容,如果未能解决你的问题,请参考以下文章

使用 Flutter 和 Firebase 实现实时在线/离线状态

如何计算 Firebase 中的 MAU?我需要 BigQuery 吗?

Google Analytics“活跃用户”和 Firebase“活跃用户”有啥区别?

从 Firebase 检索所有活跃用户

Firebase 实时数据库:如何在按值排序后围绕特定键检索 10 条记录?

如何使用 Flutter 从 Firebase 获取当前活跃用户?