有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

安卓从Java中的Firebase实时数据库中选择随机条目

我正在为Android开发一个应用程序,包括上传和下载图像到服务器。我使用Firebase来实现这个目的。所有图像都使用图像哈希作为文件名存储在Firebase存储器中。我还维护了一个实时数据库,其中存储了一些有关图片的信息。我需要从存储器中随机选择一张图片,所以我决定从数据库中随机选择一个条目。我发现了this答案(如您所见,int是用Javascript编写的),这表明以下代码:

const numberOfUsers = 15;
const randomIndex = Math.floor(Math.random() * numberOfUsers);
var ref = firebase.database().ref('companies/01/users');
ref.limitToFirst(randomIndex).limitToLast(1).once('value').then(snapshot =>
{
    var user = snapshot.val();
    // do something with the user data
});

但当我试图用Java构建类似的查询时

imgref.limitToFirst(random + 1).limitToLast(1).addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            randomHash = dataSnapshot.getKey();
            Log.e("get random name: ", randomHash);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

我收到一个错误

Can't call limitToLast on query with previously set limit!

所以很明显,我不能在一个查询中使用limitToFirst和LimitToLast。所以我的问题是:

  1. 有没有可能同时使用limitToFirst和limitToLast来获得一个随机条目

  2. 有没有其他方法可以从Firebase实时数据库中获取随机条目,而无需下载整个数据库或对其进行迭代(据我所知,迭代效率很低,如果我错了,请解释)

  3. 如果无法从应用程序内部执行此操作,是否有其他方法(例如,使用Firebase云功能)


共 (2) 个答案

  1. # 1 楼答案

    你需要知道你的模型是如何获得一个随机密钥的。如果它是1,2,3,4,5id,你可以像现在一样使用它,这样你就可以比较它了。 最好的方法是将所有键值存储在一个数组中,根据数组大小选择一个随机数,然后选择随机数的索引。他们使用类似答案中的代码dataSnapshot.getKey();

  2. # 2 楼答案

    如果你不反对在数据中添加额外的子项,你有几个选择

    1. 您可以使用事务对添加的每个项目进行编号,然后使用带有startAt(random).limitToFirst(1)的随机数
    2. 如果想要避免该事务,可以向每个imgref节点写入一个随机的long。然后,您可以尝试使用新生成的随机数据进行查询,如下所示:

      ref.orderByChild("randomLong").startAt(newRandomLong).limitToFirst(1).addListenerForSingleValueEvent(new ValueEventListener() {
          @Override
          public void onDataChange(DataSnapshot dataSnapshot) {
              if(dataSnapshot.getChildrenCount() > 0){
                  for(DataSnapshot snap : dataSnapshot.getChildren()){
                      //Do something with your random snapshot
                  }
              }else
              {
               /*
               Handle case where the new random Long is after the range 
               currently in the database
               ref.orderByChild("randomLong").endAt(random).limitToLast(1)
               */
              }
          }
      
          @Override
          public void onCancelled(DatabaseError databaseError) {
      
          }
      });
      

    请注意#2将根据值之间的随机范围为值添加随机权重。这种影响在较大的列表上应该不那么明显,但如果你需要一个均匀的分布,你可能希望选择#1

    如果您不能更改当前的数据结构,那么我不确定您是否可以像Alex的回答中那样迭代集合