Firebase查询双嵌套

Firebase查询双嵌套,firebase,firebase-realtime-database,Firebase,Firebase Realtime Database,鉴于firebase中的以下数据结构,我想运行一个查询来检索博客“efg”。我现在不知道用户id {Users : "1234567": { name: 'Bob', blogs: { 'abc':{..}, 'zyx':{..} } }, "7654321": { name: 'Frank', blogs:

鉴于firebase中的以下数据结构,我想运行一个查询来检索博客“efg”。我现在不知道用户id

{Users :
     "1234567": {
          name: 'Bob',
          blogs: {
               'abc':{..},
               'zyx':{..}
          }
     },
     "7654321": {
          name: 'Frank',
          blogs: {
               'efg':{..},
               'hij':{..}
          }
     }
}

Firebase API仅允许您使用其
orderByChild
equalTo
方法过滤一级深度(或)的子级

因此,在不修改/扩展当前数据结构的情况下,只保留检索所有数据并在客户端对其进行过滤的选项:

var ref=firebase.database().ref('Users');
参考一次(“值”,功能(快照){
forEach(函数(userSnapshot){
var blogs=userSnapshot.val().blogs;
var daBlog=blogs['efg'];
});
});
当然,这是非常低效的,当用户/博客数量非常多时,它不会扩展

因此,常见的解决方案是为您的树建立一个所谓的索引,将您要查找的键映射到它所在的路径:

{博客:
“abc”:“1234567”,
“zyx”:“1234567”,
“efg”:“7654321”,
“hij”:“7654321”
}
然后,您可以使用以下工具快速访问博客:

var ref=firebase.database().ref();
ref.child('Blogs/efg')。一次('value',函数(快照){
var user=snapshot.val();
ref.child('Blogs/'+user+'/Blogs')。once('value',函数(blogsnashot){
var daBlog=blogSnapshot.val();
});
});
您可能还想重新考虑是否可以重组数据,以更好地适应您的用例和Firebase的限制。他们有一些关于结构化数据的好文档,但对于不熟悉NoSQL/分层数据库的人来说,最重要的文档似乎是


另请参见我的答案,以获取一个好的示例。我还建议您阅读关于、以及这篇关于general的文章。

Firebase API仅允许您使用其
orderByChild
equalTo
方法对子级进行一级深度(或)过滤

因此,在不修改/扩展当前数据结构的情况下,只保留检索所有数据并在客户端对其进行过滤的选项:

var ref=firebase.database().ref('Users');
参考一次(“值”,功能(快照){
forEach(函数(userSnapshot){
var blogs=userSnapshot.val().blogs;
var daBlog=blogs['efg'];
});
});
当然,这是非常低效的,当用户/博客数量非常多时,它不会扩展

因此,常见的解决方案是为您的树建立一个所谓的索引,将您要查找的键映射到它所在的路径:

{博客:
“abc”:“1234567”,
“zyx”:“1234567”,
“efg”:“7654321”,
“hij”:“7654321”
}
然后,您可以使用以下工具快速访问博客:

var ref=firebase.database().ref();
ref.child('Blogs/efg')。一次('value',函数(快照){
var user=snapshot.val();
ref.child('Blogs/'+user+'/Blogs')。once('value',函数(blogsnashot){
var daBlog=blogSnapshot.val();
});
});
您可能还想重新考虑是否可以重组数据,以更好地适应您的用例和Firebase的限制。他们有一些关于结构化数据的好文档,但对于不熟悉NoSQL/分层数据库的人来说,最重要的文档似乎是


另请参见我的答案,以获取一个好的示例。我还建议您阅读关于,以及这篇关于general的文章。

鉴于您当前的数据结构,您可以检索包含您正在查找的博客文章的用户

const db = firebase.database()
const usersRef = db.ref('users')
const query = usersRef.orderByChild('blogs/efg').limitToLast(1)
query.once('value').then((ss) => {
  console.log(ss.val()) //=> { '7654321': { blogs: {...}}}
})

您需要使用
limitToLast
,因为在使用
orderByChild
时,对象是最后排序的。鉴于您当前的数据结构,您可以检索包含您正在查找的博客文章的用户

const db = firebase.database()
const usersRef = db.ref('users')
const query = usersRef.orderByChild('blogs/efg').limitToLast(1)
query.once('value').then((ss) => {
  console.log(ss.val()) //=> { '7654321': { blogs: {...}}}
})

您需要使用
limitToLast
,因为在使用
orderByChild
时对象是最后排序的,实际上非常简单-只需使用前斜杠:

db.ref('Users').child("userid/name")
db.ref('Users').child("userid/blogs")
db.ref('Users').child("userid/blogs/abc")

不需要循环或其他任何东西。

它实际上非常简单-只需使用前斜杠:

db.ref('Users').child("userid/name")
db.ref('Users').child("userid/blogs")
db.ref('Users').child("userid/blogs/abc")

不需要循环或其他任何东西。

另请参见,没有理由将博客作为用户记录的一部分。它们不是用户的逻辑“属性”,而是一个单独的实体,具有自己的数据结构、用途和读/写场景。首先,我要把它们分开(正如Frank提到的),让事情变得简单和直接。你看,博客真的没有理由成为用户记录的一部分。它们不是用户的逻辑“属性”,而是一个单独的实体,具有自己的数据结构、用途和读/写场景。首先,我会将它们分开(正如Frank提到的),使事情变得简单直接。请注意,这是现在的一项功能。我已经考虑了几分钟,但放弃了:深度查询如何解决这个问题?我不认为深度查询解决了这个问题;但是帖子说你只能查询一个层次的深度,这不再是真的。@FrankvanPuffelen,我最近读了很多你的答案(你似乎是唯一一个知道firebase的人[看看你是一名firebase工程师]),我想知道你的答案中的最终解决方案是否是一个最佳实践,或者我们应该一直尝试将信息结构化,以便只进行一次呼叫?请注意,这现在是一个功能。我已经考虑了几分钟,但放弃了:深度查询如何解决这个问题?我不认为深度查询解决了这个问题;但是帖子说你只能查询一个层次的深度,这不再是真的。@FrankvanPuffelen,我最近读了很多你的答案(你似乎是唯一一个知道firebase的人[看看你是一名firebase工程师]),我想知道你的答案中的最终解决方案是否是一个最佳实践,或者,我们是否应该始终尝试对信息进行结构化处理,以便只进行一次呼叫?