搜索节点下特定子项的存在

时间:2018-09-06 14:56:40

标签: node.js typescript firebase firebase-realtime-database firebase-admin

我正在使用 Firebase Realtime Database Cloud Functions 开发聊天应用程序。我有一个节点members,我在其中存储每个聊天室中每个用户的ID:

enter image description here

我要实现的目标(到目前为止效果不佳)是检查例如 user1 (具有 randomUid1 )与 user2处于活动状态的聊天(使用 randomUid2 )。我想出的唯一解决方案是下载整个节点(/members),并检查是否有两个uids存在数据快照的每个子节点。预先感谢。

2 个答案:

答案 0 :(得分:1)

是的,您只需要检查所有内容即可。我认为这不会成为问题,因为您的聊天次数可能会低于10万左右。

由于我不知道您正在使用的数据结构,我只是根据您的图像对其进行了刺探,因此您必须适应您的结构。

// assuming a reasonable structure
let chats = [{name: "chat1", "1": true, "5": true}, {name: "chat2", "1": true, "2": true}];

function hasChat(chats, uid1, uid2) {
    return chats.find((chat) => {
        let uids = Object.keys(chat);
        return uids.indexOf(uid1) !== -1 && uids.indexOf(uid2) !== -1;
    }) !== undefined;
}

console.log(hasChat(chats, "1", "2"));

通过使用库,可以提高性能和可读性。

答案 1 :(得分:1)

以下实施工作。但是如果不编制索引,它将最终下载members节点下的所有内容,并过滤客户端中的数据:

const ref = admin.database().ref('members');
const snap1 = await ref.orderByChild('user1').equalTo(true).once('value');
const user1Chats = Object.keys(snap1.val());

const snap2 = await ref.orderByChild('user2').equalTo(true).once('value');
const user2Chats = Object.keys(snap2.val());

user1Chats.forEach((chat) => {
  if (user2Chats.indexOf(chat) >= 0) {
    console.log('Chat in common:', chat);
  }
});

SDK将记录以下警告:

@firebase/database: FIREBASE WARNING: Using an unspecified index. Your data will be downloaded and filtered on the client. Consider adding ".indexOn": "user1" at /members to your security rules for better performance. 

您还可以尝试存储每个用户的聊天记录(除了您已有的聊天记录之外):

user1
  |
   -- chat1: true
   -- chat2: true

user2
  |
   -- chat2: true
   -- chat3: true

然后,只需查询两个用户节点,然后检查它们是否有任何重叠(上例中的chat2)即可。如果您的应用程序中的聊天室数量无限制地增长,那么从长远来看,该解决方案将表现更好。希望每个用户的聊天次数比整个应用中的活动聊天总数要少。