在Firebase中访问项目数组

时间:2018-08-04 05:34:33

标签: java android firebase firebase-realtime-database

我实际上有两个彼此相似的问题。我的问题的简要概述如下:

我正在开发的图书馆应用与书籍和作者有一对多的关系,这意味着一本书可以有许多作者。示例作者和一本书以图片的形式随附。

a sample author

a sample book

Q1。如何搜索特定作者?对于只有一名作者的书,它将始终具有第零索引。有多位作者的书怎么样?如果是这样,同一作者也可以存在于其他索引中。我想从特定作者那里获得所有书籍,我想知道这样做的最佳方法是什么?

Q2。如何确定作者的名字下是否有书籍。我实际上可以获取所有书籍并进行遍历。但是,仅进行“ EXISTS”操作将占用大量带宽。有简单的方法吗?

谢谢!

1 个答案:

答案 0 :(得分:2)

您可以迁移到Cloud Firestore,但是如果您已经在使用Firebase实时数据库,则可以实现,但是不能,而无需对数据库进行一些更改。

  

我想从特定作者那里获得所有书籍,我想知道什么是最好的方法?

不幸的是,您无法使用实际的数据库结构来实现目标。要从特定作者那里获得所有书籍,您应该考虑扩展数据结构以允许反向查找。这意味着您将创建一个名为books的新顶层集合,您应将特定作者的所有书籍作为book对象存储在其中。您的数据库架构应如下所示:

Firebase-root
  |
  --- books
        |
        --- authorIdOne
              |
              --- bookIdOne
              |     |
              |     --- id: "bookIdOne"
              |     |
              |     --- nameInEnglish: "nameInEnglish"
              |     |
              |     --- nameInSinhalese: "nameInSinhalese"
              |
              --- bookIdTwo
                    |
                    --- id: "bookIdTwo"
                    |
                    --- nameInEnglish: "nameInEnglish"
                    |
                    --- nameInSinhalese: "nameInSinhalese"

要获取特定作者的所有书籍,您需要在其ID(authorIdOne)上附加一个侦听器,并遍历其子代。

DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference yourRef = authorIdOneRef.child("books").child(authorIdOne);
authorIdOneRef.addListenerForSingleValueEvent(/* ... */);
  

如何确定作者是否有书名?

要解决此问题,您需要在exists()对象上使用DataSnapshot方法。假设您正在使用名为Book的模型类,请参见以下代码行:

ValueEventListener valueEventListener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        if(dataSnapshot.exists()) {
            for(DataSnapshot ds : dataSnapshot.getChildren()) {
                Book book = ds.getValue(Book.class);
                Log.d("TAG", book.getNameInEnglish());
            }
        }
    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {}
};
authorIdOneRef.addListenerForSingleValueEvent(valueEventListener);

但是使用String类可以实现相同的目的。

ValueEventListener valueEventListener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        if(dataSnapshot.exists()) {
            for(DataSnapshot ds : dataSnapshot.getChildren()) {
                String nameInEnglish = ds.child("nameInEnglish").getValue(String.class);
                Log.d("TAG", nameInEnglish);
            }
        }           
    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {}
};
authorIdOneRef.addListenerForSingleValueEvent(valueEventListener);

请注意,Firebase实时数据库不存储阵列。您实际上拥有的是一个对象。请参阅here更多详细信息。