如何限制在Firebase Android中检索到的子项

时间:2017-06-05 04:40:36

标签: android firebase firebase-realtime-database

我想询问如何在Android Firebase中使用受限子项检索数据。这是我的数据结构:

"chatrooms":
    "chatroom_id_1" :
        "message":
            "message_id_1":1
            "message_id_2":1
            "message_id_3":1
            "message_id_4":1
            "message_id_5":1
            "message_id_6":1
            "message_id_7":1
            "message_id_8":1
            "message_id_9":1
            "message_id_10":1
            "message_id_11":1
    "chatroom_id_2" :
            "message":
                "message_id_12":1
                "message_id_13":1
                "message_id_14":1
                "message_id_15":1
                "message_id_16":1
                "message_id_17":1
                "message_id_18":1
                "message_id_19":1
                "message_id_20":1
                "message_id_21":1
                "message_id_22":1

从上面的结构如何进行查询以检索仅包含5条消息的数据的快照?

我想拥有的dataSnapshot是这样的:

DataSnapshot { 
    key = chatroom_id_1, 
    value = {
        messages={
            message_id_1=1,
            message_id_2=1,
            message_id_3=1,
            message_id_4=1,
            message_id_5=1
        }
    }
}
DataSnapshot { 
        key = chatroom_id_2, 
        value = {
            messages={
                message_id_12=1,
                message_id_13=1,
                message_id_14=1,
                message_id_15=1,
                message_id_16=1
            }
        }
    }

可以这样做吗?因为我发现的大部分教程只能限制被检索的孩子而不是内心的孩子。感谢

编辑:我的message_id是随机生成的,所以为了获得message_id,我必须使用带迭代器的DataSnapshot。这是我的检索数据代码

public void retrieveChatRoom(final Callback callback){
        DatabaseReference ref = reference.child("chatrooms");
        ref.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                callback.onDataChanged();
                Iterator i = dataSnapshot.getChildren().iterator();
                while (i.hasNext()) {
                    DataSnapshot dataSnapshot1 = (DataSnapshot) i.next();
                    callback.dataReceived(dataSnapshot1);
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });
    }

问题是DataSnapshot返回我聊天室内的所有chat_message,我可以将其限制为仅返回5条消息吗?

2 个答案:

答案 0 :(得分:0)

要检索子节点的子集,请使用Firebase queries。如果要将子节点同步到某个键,则使用:

Query query = ref.child("chatroom_id_1/message")
    .orderByKey()
    .endAt("message_id_5");
query.addValueEventListener(new ValueEventListener() {
  @Override
  public void onDataChange(DataSnapshot dataSnapshot) {
    for (DataSnapshot childSnapshot: dataSnapshot.getChildren()) {
        System.out.println(childSnapshot.getKey());
    }
  }
  ...

如果您只想从某个位置获取5条消息:

Query query = ref.child("chatroom_id_1/message")
    .orderByKey()
    .limitToFist(5);
query.addValueEventListener(new ValueEventListener() {
  @Override
  public void onDataChange(DataSnapshot dataSnapshot) {
    for (DataSnapshot childSnapshot: dataSnapshot.getChildren()) {
        System.out.println(childSnapshot.getKey());
    }
  }
  ...

<强>更新

Firebase数据库查询可以根据您执行它们的位置的每个子节点的固定属性(或路径)来限制结果。无法一次性检索每个聊天室的最后5条消息。您可以检索特定聊天室的最后5条消息。或者最后5个聊天室。

答案 1 :(得分:0)

尽管可以这样做,但您当前的数据库结构并不适合这些类型的查询。

您需要“反规范化”您的数据。 而不是将所有消息存储在聊天室中,而不是将它们分开。

诀窍是将所有邮件分别存储为“chatroom_id”下的列表。这样,您可以轻松获取给定聊天室的所有消息,并使用firebase limit apis。

这样的东西
/chatrooms
    - chatroom_id1
        {
            name,
            last_message,
            timestamp
        }

/messages
    - chatroom_id   //<-- Notice this
        {
            sender,
            content,
            timestamp
        }           //<-- Add new child messages here

然后,您可以获取给定chatroom_id的消息,例如

//Get chatroom list and details
ref.child("chatrooms")
ref.child("chatrooms").child("some_chatroom_id")

//Get limited messages
ref.child("messages").child("some_chatroom_id").limitToFirst(10)

当您只需要一个聊天室列表时,这将有额外的好处,即减少带宽使用,从那时起,将不会获取整个消息列表。

Firebase Reference