java - 如何在节点 Firebase 中获得唯一的随机产品?

标签 java android firebase firebase-realtime-database

数据:

- products
   - -L74Pc7oVY22UsCETFBv
       - name: "gjwj"
       - category: "hreggrrg"
       - location: "vjhiwehifwe"
       - price: 44
       - color: fassaf
   - -L74uJ7oVYcVNyCteFBz
       - name: "uygfwh"
       - category: "hhhjwwwom"
       - location: "pervrr"
       - price: 33
       - color: yrtrr
   ......................

我在节点 products 中有很多产品, 1000 多种产品。我可以在 ListView 中显示所有内容.我只想向用户显示一个唯一的随机数,例如亮点,但不是全部下载,只有一个。

代码:
ValueEventListener v = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for(DataSnapshot child : dataSnapshot.getChildren()) {
            String name = (String) child.child("name").getValue().toString();
            Toast.makeText(MainActivity.this, name, Toast.LENGTH_SHORT).show();
            //How to get?????
        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {}
};
FirebaseDatabase.getInstance().getReference().addListenerForSingleValueEvent(v);

如何在节点 Firebase 中获得唯一的随机产品?

最佳答案

好吧,这里有一些关于 SOF 的好答案,但它们是分开的,所以我将尝试用两种方法回答你的问题。

但首先,在编写一些代码之前,我可以告诉你这段代码不起作用,因为你在引用文献中错过了一个 child ,即 products ,显然假设 products node 是 Firebase 数据库根目录的直接子节点。

实际答案:

假设您的数据库结构如下所示(其中 products 节点是 Firebase 数据库的直接子节点):

Firebase-root
   |
   --- products
         |
         --- productIdOne
         |      |
         |      --- name: "gjwj"
         |      |
         |      --- category: "hreggrrg"
         |      |
         |      --- location: "vjhiwehifwe"
         |      |
         |      --- price: 44
         |      |
         |      --- color: "fassaf"
         |
         --- productIdTwo
         |      |
         |      --- name: "uygfwh"
         |      |
         |      --- category: "hhhjwwwom"
         |      |
         |      --- location: "pervrr"
         |      |
         |      --- price: 33
         |      |
         |      --- color: "yrtrr"
         |
         --- //And so on

要获得随机产品,请使用以下代码:
ListView listView = (ListView) findViewById(R.id.list_view);
ArrayAdapter arrayAdapter = new ArrayAdapter<>(context, android.R.layout.simple_list_item_1, randomProductList);
listView.setAdapter(arrayAdapter);
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference productsRef = rootRef.child("products"); //Added call to .child("products")
ValueEventListener valueEventListener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        List<String> productList = new ArrayList<>();
        for(DataSnapshot ds : dataSnapshot.getChildren()) {
            String name = ds.child("name").getValue(String.class);
            productList.add(name);
        }

        int productListSize = productList.size();
        List<String> randomProductList = new ArrayList<>();

        randomProductList.add(new Random().nextInt(productListSize)); //Add the random product to list
        arrayAdapter.notifyDatasetChanged();
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        Log.d(TAG, "Error: ", task.getException()); //Don't ignore errors!
    }
};
productsRef.addListenerForSingleValueEvent(valueEventListener);

为了获得所有产品,您需要遍历 products 的所有子节点节点。所以调用child("products")是强制性的。

如果您想要多个随机产品,那么您可以创建一个循环并在 randomProductList 中添加任意数量的随机产品。 .

这被称为经典解决方案,您可以将其用于仅包含少量记录的节点,但如果您害怕获取大量数据,那么我会向您推荐第二种方法。这还需要通过添加一个名为 productIds 的新节点来对您的数据库进行一些更改。 .您的数据库结构应如下所示:
Firebase-root
   |
   --- products
   |     |
   |     --- productIdOne
   |     |      |
   |     |      --- //details
   |     |
   |     --- productIdTwo
   |            |
   |            --- //details
   |      
   --- productIds
          |
          --- productIdOne: true
          |
          --- productIdTwo: true
          |
          --- //And so on

因此,正如您在问题中提到的,如果您想避免下载整个 products包含具有所有属性的所有产品的节点,您必须创建一个名为 productIds 的单独节点.因此,要获得单个产品,您只需下载一个仅包含产品 ID 的简单节点。

这种做法称为非规范化(复制数据),是 Firebase 的常见做法。为了更好地理解,我建议您观看此视频,Denormalization is normal with the Firebase Database .

但是请记住,就像您在这个新创建的节点中添加随机产品一样,您需要在不再需要它们时删除它们。

因此,要获得随机产品,您需要查询数据库两次。请看下面的代码:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference productIdsRef = rootRef.child("productIds");
ValueEventListener valueEventListener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        List<String> productIdsList = new ArrayList<>();
        for(DataSnapshot ds : dataSnapshot.getChildren()) {
            String productId = ds.getKey();
            productIdsList.add(productId);
        }

        int productListSize = productList.size();
        List<String> randomProductList = new ArrayList<>(););

        DatabaseReference productIdRef = rootRef.child("products").child(productIdsList.get(new Random().nextInt(int productListSize));
        ValueEventListener eventListener = new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                String name = dataSnapshot.child("name").getValue(String.class);
                Log.d("TAG", name);
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
                Log.d(TAG, "Error: ", task.getException()); //Don't ignore errors!
            }
        };
        productIdRef.addListenerForSingleValueEvent(eventListener);
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        Log.d(TAG, "Error: ", task.getException()); //Don't ignore errors!
    }
};
productIdsRef.addListenerForSingleValueEvent(valueEventListener);

当您对 Firebase 数据库执行查询时,可能会有多个结果。所以dataSnapshot包含这些结果的列表。即使只有一个结果,dataSnapshot对象将包含一个结果的列表。

关于java - 如何在节点 Firebase 中获得唯一的随机产品?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72435777/

相关文章:

android - 我可以使用来自不同 google 项目的两个 google-services json 文件吗?

java - CertPathValidator 和 CertPathBuilder 之间的概念区别是什么?

java - 从多模块项目发布 bom

java - 在 Web 应用程序之间共享应用程序范围数据数据?

javascript - 如何使用包含 firebase 存储的 uid 在另一个文件夹中创建文件夹

ios - 我的 IBAction 中的 NSDictionary 变为零

java - 我如何知道 javax.jnlp.PrintService 何时完成打印我的 Printable 对象

android - 如何重用布局/布局属性并在之后更改单个属性

android - SurfaceView.onDraw 未调用

android imageview 显示质量差