如何在Firebase中构建数据以避免N + 1选择? [英] How to structure data in Firebase to avoid N+1 selects?

查看:152
本文介绍了如何在Firebase中构建数据以避免N + 1选择?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于Firebase安全规则不能用于过滤子项,因此在基本的多用户应用程序中构建用于高效查询的数据的最佳方法是什么?我已经阅读了几个指南,但是当它们超出给定的例子时,它们看起来会崩溃。



假设您有一个像WhatsApp这样的基本消息应用程序。用户可以与其他用户组打开聊天,在他们之间发送私人消息。以下是我如何在Firebase中组织的最初想法(有点类似于):

  {
users:{$ rel =nofollow> b $ b $ uid:{
name:string,
chats:{
$ chat_uid:true,
$ chat2_uid:true
}
}
},
聊天:{
$ uid:{
messages:{
message1:'first message',
message2:'another message'



$ b $ / code $ / pre
$ b

Firebase权限可以设置为只允许用户读取在其用户对象中标记为 true chats (并限制任意添加到 chats object等)。



然而这个布局需要N + 1个选择几个常见的情况。例如:要构建主屏幕,应用程序必须先检索用户的 chats 对象,然后制作 get 请求每个线程获取其信息。同样的事情,如果用户想要搜索他们的对话特定的字符串:应用程序必须运行一个单独的请求,每个聊天他们有权访问,以查看是否匹配。



我很想设置一个node.js服务器来针对 chats 树运行根认证的查询,并完全跳过客户端的firebase代码。但是这首先破坏了Firebase的用途。

有没有办法像使用Firebase权限一样组织这样的数据,并避免N + 1选择问题?

p>

解决方案

似乎并不一定需要避免n + 1个查询,并且Firebase专门设计为在执行n +1选择,尽管对于来自关系数据库背景的开发人员来说是违反直觉的。



Firebase 2.4.2文档后面有一个令人欣慰的消息:

  //列出所有Mary的组名
var ref = new Firebase(https://docs-examples.firebaseio.com/web/org );
$ b $ //获取Mary's组的列表
ref.child(users / mchen / groups)。on('child_added',function(snapshot){
//为每个组获取名称并打印它
String groupKey = snapshot.key();
ref.child(groups /+ groupKey +/name\").once('value',函数(快照){
System.out.println(Mary是这个组的成员:+ snapshot.val());
});
});




单独查找每个记录真的可以吗?是。 Firebase协议使用Web套接字,客户端库对传入和传出的请求进行了大量的内部优化。在获得数万条记录之前,这种方法是完全合理的。实际上,下载数据所需的时间(即字节数)使连接开销的任何其他问题重演。



Since Firebase security rules cannot be used to filter children, what's the best way to structure data for efficient queries in a basic multi-user application? I've read through several guides, but they seem to break down when scaled past the examples given.

Say you have a basic messaging application like WhatsApp. Users can open chats with other groups of users to send private messages between themselves. Here's my initial idea of how this could be organized in Firebase (a bit similar to this example from the docs):

{
    users: {
        $uid: {
            name: string, 
            chats: {
                $chat_uid : true, 
                $chat2_uid: true
            }
        }
    },
    chats: {
        $uid: {
            messages: {
                message1: 'first message', 
                message2: 'another message'
            }
        }
    }
} 

Firebase permissions could be set up to only let users read chats that are marked true in their user object (and restrict adding arbitrarily to the chats object, etc).

However this layout requires N+1 selects for several common scenarios. For example: to build the home screen, the app has to first retrieve the user's chats object, then make a get request for each thread to get its info. Same thing if a user wants to search their conversations for a specific string: the app has to run a separate request for every chat they have access to in order to see if it matches.

I'm tempted to set up a node.js server to run root-authenticated queries against the chats tree and skip the client-side firebase code altogether. But that's defeating the purpose of Firebase in the first place.

Is there a way to organize data like this using Firebase permissions and avoid the N+1 select problem?

解决方案

It appears that n+1 queries do not necessarily need to be avoided and that Firebase is engineered specifically to offer good performance when doing n+1 selects, despite being counter-intuitive for developers coming from a relational database background.

An example of n+1 in the Firebase 2.4.2 documentation is followed by a reassuring message:

// List the names of all Mary's groups
var ref = new Firebase("https://docs-examples.firebaseio.com/web/org");

// fetch a list of Mary's groups
ref.child("users/mchen/groups").on('child_added', function(snapshot) {
  // for each group, fetch the name and print it
  String groupKey = snapshot.key();
  ref.child("groups/" + groupKey + "/name").once('value', function(snapshot) {
    System.out.println("Mary is a member of this group: " + snapshot.val());
  });
});

Is it really okay to look up each record individually? Yes. The Firebase protocol uses web sockets, and the client libraries do a great deal of internal optimization of incoming and outgoing requests. Until we get into tens of thousands of records, this approach is perfectly reasonable. In fact, the time required to download the data (i.e. the byte count) eclipses any other concerns regarding connection overhead.

这篇关于如何在Firebase中构建数据以避免N + 1选择?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆