我想在聊天室中跟踪和报告用户,我不知道如何最好地在Firebase中构建数据。
一般情况
获取数据
我们可以访问返回json的API,我计划每1分钟轮询API,查找所有聊天室(room_id),然后请求每个房间的所有用户(user_id)。
设置数据
数据的设置完全在我们的控制之下。
报告我想能得到
问题
发布于 2015-09-09 21:08:19
火源时间会为我盖上每一张记录吗?还是我需要把时间写在每一张唱片里?
不是,但您可以使用Firebase.ServerValue.TIMESTAMP,如the docs中所提到的。Firebase只存储您要求它存储的内容。
它是最好的使用unix时代还是一个更容易理解的日期时间?
在所有的日期时间(如果可能的话)使用Firebase.ServerValue.TIMESTAMP (这是一个Unix )。与使用new Date().getTime()或依赖于本地机器时间的任何其他方法相比,这确保了一致性和正确性(这通常是错误的,因此最终会导致数据混乱)。
Unix时代也是非常适合Firebase查询能力的整数,具体来说,我们可以使用.startAt()和.endAt()从特定的日期范围(如下面的答案所示)获取信息。
我应该如何在防火墙中构造这些数据?
您需要问的第一个问题是“我将如何使用这些数据?”Firebase不是一个很大的SQL数据库,在这里我们可以得到正确的结构,然后依靠复杂的查询来弥补我们的错误。
当您在Firebase中构建结构时,请确保它允许您以指定的方式加载数据。这意味着,如果您知道要从其中加载数据的room_id列表,那么您的房间结构应该基于这些if。
为一个简单的聊天室考虑这样的结构(我们将使用$表示法来表示通配符)。
{
"rooms": {
$room_id: {
"users": {
$user_id: true
},
"_meta": {
closed: Boolean
},
"messages": {
$message_id: {
"user_id": $user_id,
"text": ""
}
}
}
},
"users": {
$user_id: {...}
}
}当一个id为abe的用户加入一个带有room_id of room_one的房间时,我们知道他们需要通过将location /rooms/room_one/users/abe设置为true来标记自己为聊天室的活动成员。
我们加入一个房间的功能是这样的。
function joinRoom(room_id) {
// We assume `ref` is a Firebase reference to the root of our Firebase
var roomRef = ref.child("rooms").child(room_id);
roomRef.child("users").child(myUserId).set(true);
return roomRef;
}这是很具体的。我们得到了一些信息,而且由于我们的数据结构是合乎逻辑的,所以我们可以很容易地假设需要编写哪些数据,而无需从Firebase加载任何数据。
不过,这对你的情况来说还不够好,因为你也想要报告。我们将根据您的需要逐步改进我们的结构
从x到y日期和时间,我们看到了多少独特的用户?
假设你是在每间房的基础上说话,这是一个容易的改变。
{
"rooms": {
$room_id: {
"users": {
$user_id: true
},
"users_history": {
$push_id: {
user_id: ...,
timestamp: ...
}
},
"messages": {
$message_id: {...}
}
}
},
"users": {
$user_id: {...}
}
}我们添加/users/$room_id/users_history位置。这是用户每次进入这个房间的名单。我们增加了一些复杂性,所以我们的联接室功能看起来像这样。
function joinRoom(room_id) {
var roomRef = ref.child("rooms").child(room_id);
roomRef.child("users_history").push({
user_id: myUserId,
timestamp: Firebase.ServerValue.TIMESTAMP
});
roomRef.child("users").child(myUserId).set(true);
return roomRef;
}现在,我们可以轻松地报告在给定时间内使用Firebase Query的用户数量。
function roomVisitors(room_id, start_datetime, end_datetime) {
var roomRef = ref.child("rooms").child(room_id),
queriedRoomRef = roomRef
.orderByChild('timestamp')
.startAt(start_datetime.getTime())
.endAt(end_datetime.getTime());
// Assuming we use some ES6 promise library
return new Promise(function (resolve, reject) {
queriedRoomRef.once("value", function (users) {
/* Users will be a snapshot of all people who
came into the room for the given range of time. */
resolve(users.val());
}, function (err) {
reject(err);;
});
});
}我们稍后会讨论做这件事是否真的是“特定的”,但这是一般的想法。
1名用户从x到y的在线时间
我们还没有充实我们的/users/$user_id结构,但我们必须在这里这样做。在这种情况下,我们需要查找用户上网时间的唯一信息是他们的user_id。因此,我们必须将这些信息存储在/user/$user_id下,因为如果我们将其存储在/rooms/下,我们将不得不为所有房间加载数据并循环遍历以找到相关的用户信息,这不是很具体。
{
"rooms": {
$room_id: {
"users": {
$user_id: true
},
"users_history": {
$push_id: {
user_id: ...,
timestamp: ...
}
},
"messages": {
$message_id: {...}
}
}
},
"users": {
$user_id: {
"online_history": {
$push_id: {
"action": "", // "online" or "offline"
"timestamp": ...
}
}
}
}
}现在我们可以构建一个ref.onAuth(func)来跟踪我们的在线时间。
var userRef;
ref.onAuth(function (auth) {
if (!auth && userRef) {
// If we haven no auth, i.e. we log out, cancel any onDisconnect's
userRef.onDisconnect().cancel();
// and push a record saying the user went offline
userRef.child("online_history").push({
action: "offline",
timestamp: Firebase.ServerValue.TIMESTAMP
});
} else if (auth) {
userRef = ref.child('users').child(auth.uid);
// add a record that we went offline
userRef.child('online_history').push({
action: "online",
timestamp: Firebase.ServerValue.TIMESTAMP
});
// and if the user disconnects, add a record of going offline
userRef.child('online_history').push().onDisconnect().set({
action: "offline",
timestamp: Firebase.ServerValue.TIMESTAMP
});
}
});使用这种方法,我们现在可以编写一个函数来循环在线/脱机日志,并使用上面使用的相同的查询方法将给定范围的时间加起来,但我将把这作为一个练习留给读者。
关于特性和性能的说明
这两个报告功能都不具体。当我们得到在第一个查询中访问一个房间的用户列表时,我们抓取一个装满用户名的大对象,然后将所有的数据解压到客户端,而我们真正想要的只是唯一访问者数量的整数值。
在这种情况下,您确实希望使用服务器端SDK雇用NodeJS工作人员。这个工作人员可以坐下来观察数据结构的变化,并在数据变化时自动汇总数据,这样您的客户端就可以查看像/rooms/$room_id/_meta/analytics/uniqueVisitorsThisWeek这样的位置,并得到一个类似于10的数字。
关键是,存储是便宜的,总结和缓存这样的数据是很便宜的,但前提是它是服务器端的。如果您不是特定的,并且加载太多并且试图执行总结客户端,那么您将浪费CPU周期和带宽。
如果您从Firebase将数据加载到客户端,而不显示数据,则应该对数据结构进行重新处理,使其更加具体。
https://stackoverflow.com/questions/32480615
复制相似问题