首页 > 解决方案 > 访问 Firebase 中的项目数组

问题描述

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

我正在开发的图书馆应用程序与书籍和作者具有一对多的关系,这意味着一本书可以有多个作者。示例作者和一本书作为图像附加。

样本作者

样书

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

Q2。如何查明作者名下是否有书籍。我实际上可以获取所有书籍并遍历它。但是,仅执行“EXISTS”操作就需要大量带宽。有没有简单的方法来做到这一点?

提前致谢!

标签: javaandroidfirebasefirebase-realtime-database

解决方案


您可以迁移到 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 实时数据库不存储数组。你实际上拥有的是一个对象。请参阅此处的更多详细信息。


推荐阅读