Java Firebase-通过(大)子级的存在进行查询
我有一个这样的数据路径Java Firebase-通过(大)子级的存在进行查询,java,firebase,firebase-realtime-database,Java,Firebase,Firebase Realtime Database,我有一个这样的数据路径 events -KntTJCVBtbrb79dHemC dateStamp: 1498747689858 admin: "rPxwIzEtJaRbEH6ujkP5QJgpHDp2" attending: rPxwIzEtJaRbEH6ujkP5QJgpHDp2: true MtaPwHEKMEOTXBRdXBuXuS3gst12: false 我想获得有特定用户参加的
events
-KntTJCVBtbrb79dHemC
dateStamp: 1498747689858
admin: "rPxwIzEtJaRbEH6ujkP5QJgpHDp2"
attending:
rPxwIzEtJaRbEH6ujkP5QJgpHDp2: true
MtaPwHEKMEOTXBRdXBuXuS3gst12: false
我想获得有特定用户参加的活动。换句话说,我想获取所有存在关键字“Attenting/[some user id]”的事件
问题是我只能通过按该路径的特定值(true或false)进行过滤来实现,如下所示:
eventsRef.orderByChild("attending/" + user.getId()).equalTo(true).addListenerForSingleValueEvent(...)
这只适用于键的值为真的情况,所以要得到我需要的,我必须做两个调用,一个用于值为真的时候,另一个用于值为假的时候
我尝试使用startAt(true)和endAt(false)(和viceversa),但最终没有返回任何结果
我不确定我错过了什么
编辑
我应该指定我知道这可以通过非规范化和使用另一个节点作为关系“表”来实现,我只是想知道上面的方法是否可行,因为它已经非常接近了,并且可以避免先获取密钥然后再检索实际数据的两步过程。这里是数据非规范化的开始 您描述的是查询孙子的唯一方法。当然,正如你提到的,它不是非常直观、有用或快速 您需要做的是为参加给定事件的用户创建一个单独的节点。您可以将其命名为
UsersAttendingTheEvent
。这将把事件键作为子项。每当用户开始参加给定的事件时,将用户密钥添加为事件密钥的子项(因此,UsersAttendingTheEvent
的孙辈)
那么比如说,
UsersAttendingTheEvent:{
-KntTJCVBtbrb79dHemC:{
rPxwIzEtJaRbEH6ujkP5QJgpHDp2: true
MtaPwHEKMEOTXBRdXBuXuS3gst12: false
}}
现在,当您想要运行查询时,只需对UsersAttendingTheEvent
运行一个简单的orderByChild(userId)
查询,即可获得用户正在参与的事件的所有密钥
接下来,您可以从主事件/eventKey
获取事件详细信息。这看起来像是一个额外的调用,但这正是Firebase数据反规范化的设计方式。此外,它的工作速度相当快
编辑
您的startAt(true
)和endAt(false)
未返回任何内容的原因是调用orderByChild()
时,返回的项目顺序如下:-
请尝试仅使用
startAt(true)
。如果您确保您的成员键只有true或false值,并且在true
之后不会按字典顺序返回其他值,那么这将起作用。以下是数据反规范化的时间
您所描述的是查询孙子的唯一方法。当然,正如您所提到的,它不是非常直观、有用或快速
您需要做的是为参与给定事件的用户创建一个单独的节点。您可以将其命名为UsersAttendingTheEvent
。这将事件键作为子项。每当用户开始参与给定事件时,都将用户键添加为事件键的子项(因此,usersattendingthevent
的孙子
那么比如说,
UsersAttendingTheEvent:{
-KntTJCVBtbrb79dHemC:{
rPxwIzEtJaRbEH6ujkP5QJgpHDp2: true
MtaPwHEKMEOTXBRdXBuXuS3gst12: false
}}
现在,当您想要运行查询时,只需对UsersAttendingTheEvent
运行一个简单的orderByChild(userId)
查询,即可获得用户正在参与的事件的所有密钥
接下来,您可以从主事件/eventKey
获取事件详细信息。这看起来像是一个额外的调用,但这正是Firebase数据反规范化的设计方式。此外,它的工作速度相当快
编辑
您的startAt(true
)和endAt(false)
未返回任何内容的原因是调用orderByChild()
时,返回的项目顺序如下:-
尝试仅使用
startAt(true)
。如果您确保您的成员键只有true或false值,并且在true
之后不会按字典顺序返回其他值,那么这将起作用。您只能查询1层深度,您必须更改结构。我不确定这是否正确。正如您在我的帖子中看到的,使用孙子值进行查询是有效的只是我关心的是存在的键,而不是它有什么价值。你只能查询1层,你必须改变结构。我不确定这是真的。正如你从我的帖子中看到的,使用孙子的值进行查询是有效的,我只是关心存在的键,而不是它有什么价值。我应该提到我已经有了这个所有这些都是非规范化的,只是想看看这是否可以避免获取密钥然后获取实际对象的两步过程,但是谢谢!哦,那很好。也许有一种方法可以让你这样做。让我编辑我的答案。回答很好Rohan。@Roberto:你当前的结构可以很容易地显示每个事件的用户列表。But如果要显示每个用户的事件列表,还应存储每个用户的事件列表。这种类型的数据复制在Firebase数据库(和许多其他NoSQL解决方案)上非常正常。我建议大家阅读和观看。非常感谢@FrankvanPuffelen。很荣幸能被大家注意到!Rohan,我不知怎么错过了最新消息。这是一个很好的信息,但我认为startAt(错误)和endAt(正确)应该可以满足我的要求,但我记得那也不起作用。也许我只是换了个位置。我会在可以的时候再检查一下。谢谢!我应该提到我已经把这些都非规范化了,我只是想看看这是否可以避免两步过程,即获取密钥,然后获取实际对象,但是谢谢!哦,不是吗那就好了。