【问题标题】:Accessing an Array of Items in Firebase访问 Firebase 中的项目数组
【发布时间】:2019-01-11 22:42:00
【问题描述】:

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

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

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

第二季度。如何查明作者名下是否有书籍。我实际上可以得到所有的书并遍历它。但是,仅执行“EXISTS”操作就需要大量带宽。有什么简单的方法吗?

提前致谢!

【问题讨论】:

  • 我建议使用 Firestore ,因为它具有更好的查询功能。参考这个link
  • 有没有一种简单的方法可以将我所有的现有数据迁移到 Cloud Firestore?
  • 这些Stackoverflow,Official 帖子可能会有所帮助。 (BONUS)Here 是我在网上找到的信息包。
  • 非常感谢您的链接和提醒。我研究了很多关于如何移动数据的知识,我认为我可以使用脚本来完成。
  • 很高兴您发现它很有帮助,请点赞,以便其他人可以找到它。干杯!

标签: java android firebase firebase-realtime-database


【解决方案1】:

您可以迁移到 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(/* ... */);

如何查询作者名下是否有书?

要解决这个问题,您需要在DataSnapshot 对象上使用exists() 方法。假设您使用的是名为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

【讨论】:

  • 非常感谢您的详细回答。正如你所提到的,正如我担心的那样,我的数据库结构似乎是这里的问题。因此,我认为此时迁移到 Cloud Firestore 可能是最好的选择,因为它可以确保在我实现这些功能时减少未来功能的麻烦。
  • 在这种情况下,祝你好运。这是一款非常不错的产品,而且易于学习。
  • 如果您认为我的回答对您有所帮助,请考虑接受并投票。我会很感激的。谢谢!
  • 刚刚做到了!在我没有足够的代表而无法投票之前。
猜你喜欢
  • 2014-04-18
  • 2018-08-14
  • 2019-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-30
相关资源
最近更新 更多