简体   繁体   English

Firebase Android中的数据描述排序

[英]Firebase Data Desc Sorting in Android

I am storing data in Firebase storage.我将数据存储在 Firebase 存储中。

Object Comment with attribute timestamp . Object 带有timestamp属性的Comment When I push data from device to Firebase I'm populating timestamp with currentTime and store in long data type.当我将数据从设备推送到 Firebase 时,我用 currentTime 填充timestamp并存储在long数据类型中。

When I do retrieving the data with firebaseRef.orderByChild("timestamp").limitToLast(15) result is not sorting how I expected.当我使用firebaseRef.orderByChild("timestamp").limitToLast(15)检索数据时,结果并未按照我的预期进行排序。

I even played around with rules and no result:我什至玩弄规则但没有结果:

{
    "rules": {
        ".read": true,
        ".write": true,
        ".indexOn": "streetrate",
        "streetrate": {
          ".indexOn": ".value"
        }
    }
}

I tried store timestamp in String data type, same issue.我尝试在String数据类型中存储timestamp ,同样的问题。

Firebase can order the items in ascending order by a given property and then returns either the first N items ( limitToFirst() ) or the last N items ( limitToLast() ). Firebase 可以按给定属性按升序对项目进行排序,然后返回前 N 个项目 ( limitToFirst() ) 或最后 N 个项目 ( limitToLast() )。 There is no way to indicate that you want the items in descending order.没有办法表明您想要按降序排列的项目。

There are two options to get the behavior you want:有两个选项可以获得您想要的行为:

  1. Use a Firebase query to get the correct data, then re-order it client-side使用 Firebase 查询获取正确的数据,然后在客户端对其重新排序

  2. Add a field that has a descending value to the data向数据添加具有降序值的字段

For the latter approach, it is common to have a inverted timestamp.对于后一种方法,通常使用反向时间戳。

-1 * new Date().getTime();

one good solution I find if you are using recycler view to render that data...如果您使用回收器视图来呈现该数据,我会发现一个很好的解决方案......

mLayoutManager = new LinearLayoutManager(getActivity());
mLayoutManager.setReverseLayout(true);
mLayoutManager.setStackFromEnd(true);

// And set it to RecyclerView
mRecyclerView.setLayoutManager(mLayoutManager);

it will reverse the data rendering...它将反转数据渲染...

private static class ChatMessageViewHolder extends RecyclerView.ViewHolder {
         TextView messageText;
         TextView nameText;

         public ChatMessageViewHolder(View itemView) {
             super(itemView);
             nameText = (TextView)itemView.findViewById(android.R.id.text1);
             messageText = (TextView) itemView.findViewById(android.R.id.text2);
         }
     }

     FirebaseRecyclerViewAdapter<ChatMessage, ChatMessageViewHolder> adapter;
     ref = new Firebase("https://<yourapp>.firebaseio.com");

     RecyclerView recycler = (RecyclerView) 

     findViewById(R.id.messages_recycler);
         recycler.setHasFixedSize(true);

         //////////////////////////////////////////////////////////
         mLayoutManager = new LinearLayoutManager(getActivity());
         mLayoutManager.setReverseLayout(true);
         mLayoutManager.setStackFromEnd(true);
         recycler.setLayoutManager(mLayoutManager);
         /////////////////////////////////////////////////////////

         adapter = new FirebaseRecyclerViewAdapter<ChatMessage, ChatMessageViewHolder>(ChatMessage.class, android.R.layout.two_line_list_item, ChatMessageViewHolder.class, mRef) {
         public void populateViewHolder(ChatMessageViewHolder chatMessageViewHolder, ChatMessage chatMessage) {
             chatMessageViewHolder.nameText.setText(chatMessage.getName());
             chatMessageViewHolder.messageText.setText(chatMessage.getMessage());
         }
     };
     recycler.setAdapter(mAdapter);

I don't see any option to reverse the data.我没有看到任何反转数据的选项。 But One Brute way is to get the data.但一种粗暴的方法是获取数据。

List<ModelClass> mList=new ArrayList();
public void onDataChange(DataSnapshot dataSnapshot) 
{
     mList.clear();
     for(DataSnapshot children: dataSnapshot.getChildren()){
        ModelClass modelClass=children.getValue(ModelClass.class);
        mList.add(modelClass);
     }
     Collections.reverse(mList);
     Adapter.notifyDataSetChanged();
}

I have solved problem by extending FirebaseListAdapter and overriding getItem method:我通过扩展 FirebaseListAdapter 和覆盖 getItem 方法解决了问题:

public abstract class ReverseFirebaseListAdapter<T> extends FirebaseListAdapter<T>  {

public ReverseFirebaseListAdapter(Activity activity, Class<T> modelClass, int modelLayout, Query ref) {
    super(activity, modelClass, modelLayout, ref);
}

public ReverseFirebaseListAdapter(Activity activity, Class<T> modelClass, int modelLayout, DatabaseReference ref) {
    super(activity, modelClass, modelLayout, ref);
}

@Override
public T getItem(int position) {
  return super.getItem(getCount() - (position + 1));
}

} }

The @Monet_z_Polski approach, based on @Monet_z_Polski 方法,基于

@Override
public T getItem(int position) {
  return super.getItem(getCount() - (position + 1));
}

does have a weird effect on not update FirebaseRecyclerView automatically (PopulateViewHolder is not triggered in realtime changes).不自动更新 FirebaseRecyclerView 确实有一个奇怪的效果(PopulateViewHolder 不会在实时更改中触发)。 So, the best option is use a negative key to index the data .因此,最好的选择是使用负键来索引数据

add a column namely timestamp with values (-1*System.currentTimeMillis()) and while fetching data use orderByChild("timestamp").limitToFirst(15) or orderByChild("timestamp").limitToLast(15) according to your requirement.根据您的要求添加一列,即带有值的时间戳(-1*System.currentTimeMillis())并在获取数据时使用orderByChild("timestamp").limitToFirst(15)orderByChild("timestamp").limitToLast(15) it is smartway to get data in sorted manner, as firebase has no rule for descending order.以排序方式获取数据是一种聪明的方法,因为 Firebase 没有降序规则。

Sorting child items by TIMESTAMP can be done using android.support.v7.util.SortedList可以使用android.support.v7.util.SortedList按 T​​IMESTAMP 对子项进行排序

  class post{
private Object time; 

public Object getTime() {
        return time;
    }

public void setTime(Object time) {
    this.time = time;
}
                        ...//rest code}

SortedList<post> data;

 data = new SortedList<post>(post.class, new SortedList.Callback<post>() {
        @Override
        public int compare(post o1, post o2) {
            Long o1l = Long.parseLong(o1.getTime().toString());
            Long o2l = Long.parseLong(o2.getTime().toString());

            return o2l.compareTo(o1l);
        }......//rest code


ref.addChildEventListener(new ChildEventListener() {
              @Override
              public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                 mSwipeRefreshLayout.setRefreshing(true);
                  post p=dataSnapshot.getValue(post.class);


                  data.add(p);



              }...// rest code

android.support.v7.util.SortedList can also be used with RecyclerView android.support.v7.util.SortedList也可以与RecyclerView一起使用

If you are doing it on web then you can push values in an array and then print the stored values in reverse order.如果您在 Web 上执行此操作,则可以将值推送到数组中,然后以相反的顺序打印存储的值。

var a=[]; //declaring an array a.
var num=snapshot.numChildren(); //storing number of children in var num.
a.push(snapshot.val()); // pushing data in the array.
if (a.length==num){ //checking if length of array is same as number of children.
a.reverse(); //reversing the array elements.
for(i=0; i<num; i++){
a[i].name;//this will sort the data in descending order.
}
}

Based on Himanshus answer but Im using kotlin and instead of the timestamp in the question Im ordering by score which should be similar.基于 Himanshus 的回答,但我使用 kotlin 而不是问题中的时间戳,我按分数排序,这应该是相似的。 I'm not sure if firebase has an ascending or descending function but this is what ended working for me in my current project.我不确定 firebase 是否具有升序或降序函数,但这就是在我当前的项目中为我工作的结果。 I hope it will help someone else in the near future.我希望它会在不久的将来帮助其他人。

FirebaseFirestore.getInstance().collection("leaderboard")
            .orderBy("score")
            .addSnapshotListener { snapshot, exception ->

                if (exception != null) {
                    Log.e("Exception:", "Could not retrieve scores ${exception.localizedMessage}")
                }

                if (snapshot != null) {
                    scores.clear()

                    for (document in snapshot.documents) {
                        val data = document.data

                        val name = data?.get("name") as? String
                        val score = data?.get("score") as? Number

                        val documentId = document.id

                        val newScore = Score(name, score, documentId)
                        scores.add(newScore)
                    }

                    scores.reverse()
                    scoresAdapter.notifyDataSetChanged()
                }
            }

This is what worked for me.这对我有用。 Happy coding!快乐编码!

This is a client side solution , it will sort the data according to a specific child in firebase database after filling the list这是一个客户端解决方案,它会在填充列表后根据 firebase 数据库中的特定子项对数据进行排序。

Collections.sort(list, new Comparator<ModuleClass>() {
                    @Override
                    public int compare(ModuleClass module, ModuleClass t1) {
                        return Integer.compare(module.getViews(), t1.getViews());
                    }
                });

If you are passing an arraylist to the recyclerView you can do something like this:如果您将 arraylist 传递给 recyclerView,您可以执行以下操作:

FirebaseDatabase.getInstance().getReference().child("parent_id")
.child("id").orderByChild("count");

    tpDBListener = tpDatabaseRef.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) {
            tpUploads.clear();
            for(DataSnapshot postSnapshot : snapshot.getChildren()){
                newUpload pupload = postSnapshot.getValue(newUpload.class);
                pupload.setKey(postSnapshot.getKey());
                
                    tpUploads.add(pupload);//add new object on end
                    //tpUploads.add(0,pupload);//add new object at beginning
                
            }
            tpAdapter.notifyDataSetChanged();
        }

        @Override
        public void onCancelled(@NonNull DatabaseError error) {
            Toast.makeText(home.this, error.getMessage(),Toast.LENGTH_SHORT).show();
        }
    });

to flip the order so first is last and last is first I recommend when putting the value in the database putting it as 9999999999 and then -1 for what ever ordering you want then use the: if you are not ordeing them by a value or a child.翻转订单,所以第一个是最后一个,最后一个是第一个我建议在将值放入数据库时​​将其作为 9999999999 然后 -1 用于您想要的任何订购然后使用:如果您没有按值或孩子。

 tpUploads.add(0, pupload);//add new object at beginning

if you want to order by a value this is the better approach and initialize it in db as 9999999999 and then -1 for its value如果您想按值排序,这是更好的方法,并在 db 中将其初始化为 9999999999,然后将其值设为 -1

.orderBy("child_ID") 

firebase will try to read each digit for example 1 is before 6 but 10 will also come before 6 because of the first digit. firebase 将尝试读取每个数字,例如 1 在 6 之前,但由于第一个数字,10 也将在 6 之前。 That is why I start off with 9999999999 as the starting value and decrease acordingly这就是为什么我以 9999999999 作为起始值并相应减小的原因

public static List<'YourModel> desireList= new ArrayList<>();公共静态列表<'你的模型>希望列表=新的数组列表<>();

//Your Realtime Database Query on "ORDERBY","Name" or Key or etc. //您对“ORDERBY”、“名称”或键等的实时数据库查询。

@Override
public void onDataChange(DataSnapshot dataSnapshot) 
{
 desireList.clear();
 List<YourModel>tempList = new ArrayList<>();//Create temp list Object.

 for (DataSnapshot dataSnapshotList : dataSnapshot.getChildren()) 
   {
    tempList.add(new YourModel(
       dataSnapshotList.child("Name").getValue() + "",
       dataSnapshotList.getKey() + "",
       dataSnapshotList.child("ORDERBY").getValue() + ""));
   }
       //Save object list in reverse order start.
       for (int i =tempList.size(); i>0; i--)
        {
          desireList.add(tempList.get(i-1));
        }
       //Save object list in reverse order end.

        tempList.clear(); //To clear memory only(not required.)
        //Then update your adapter
        yoursAdapter.notifyDataSetChanged();
 }

Sort at client side is simple and not require more system resources.在客户端排序很简单,不需要更多的系统资源。 Each data snapshot has previousChildkey field.每个数据快照都有 previousChildkey 字段。 If you want to desc sorting, imagine previousChildkey is nextChildKey.如果你想进行排序,想象 previousChildkey 是 nextChildKey。 Here are my sample:这是我的示例:

class LessonFirebaseArray<ObjectModel>{

  private ArrayList<ObjectModel> mItems;
  ...
  public LessonFirebaseArray() {
    mItems = new ArrayList<>();
  }

  public int addItem(ObjectModel item, boolean isReverse){
    int index;
    if (item.getPreviousChildKey() != null) {
      index = getIndexForKey(item.getPreviousChildKey());
      if (index < 0) {
        index = mItems.size();
      }else if(index>0 && !isReverse) {
        index = index + 1;      
      }
    }else{
      index = mItems.size();
    }
    mItems.add(index, item);
    notifyInsertedListeners(index);
    return index;
  }

  private int getIndexForKey(String key) {
    int index = 0;
    for (ObjectModel snapshot : mItems) {
      if (snapshot.getKey().equals(key)) {
         return index;
      } else {
         index++;
      }
    }
    return -1;
  }

  private void notifyInsertedListeners(int index) {
    if (mListener != null) {
      mListener.onInserted(index);
    }
  }
}

It is very simple,Use -1,-2,-3, etc to store data in the firebase database.Now the data will be displayed in the reverse order in recyclerView.很简单,用-1,-2,-3等来存储firebase数据库中的数据。现在recyclerView中数据会以相反的顺序显示。

-3
-2
-1

您可以简单地反转您正在使用的列表(ListView 或 RecyclerView)。

As I understand there is no descending method , for default it is ascending only, but you can reverse it manually .据我了解,没有降序方法,默认情况下它只是升序,但您可以手动反转它 For more information read an official documantation about sorting and filtering data of Realtime Database https://firebase.google.com/docs/database/android/lists-of-data#sorting_and_filtering_data有关更多信息,请阅读有关实时数据库https://firebase.google.com/docs/database/android/lists-of-data#sorting_and_filtering_data 的排序和过滤数据的官方文档

The Current version of firebase will allow you the fetch the data by sorting it in descending order. firebase 的当前版本将允许您通过按降序排序来获取数据。

All you have to do is pass an optional bool flag to let the firebase to know to fetch the data in descending order.您所要做的就是传递一个可选的布尔标志,让 firebase 知道按降序获取数据。

Syntax句法

Query<Object?> orderBy(Object field, {bool descending = false})

Example例子

QuerySnapshot eventsQuery =
        await ref.orderBy('DateTime', descending: true).get();

Thanks谢谢

Swift 3:斯威夫特 3:

    let query = firebase.child(YourQueryPath).queryOrdered(byChild: YourQueryChild).queryLimited(toLast: YourLimit)

    query.observeSingleEvent(of: .value, with: { (snapshot) in
         // Reverse order here to get top **YourLimit** results in descending order
    })

I found the current firebase version supports descending order sorting:我发现当前的 firebase 版本支持降序排序:

citiesRef.orderBy("name", "desc").limit(3)

https://firebase.google.com/docs/firestore/query-data/order-limit-data https://firebase.google.com/docs/firestore/query-data/order-limit-data

Hope it helps希望能帮助到你

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Firebase 在 android 工作室中没有按字母顺序对文件进行排序,? - Firebase not sorting files alphabetically in android studio,? 在 Firebase 实时数据库(Javascript)中按时间戳对数据进行排序 - Sorting data by timestamp in Firebase Realtime Database (Javascript) 在 Flutter 应用程序上过滤和排序 Firebase (Firestore) 数据 - Filtering & Sorting Firebase (Firestore) Data on a Flutter App 我刚开始使用 firebase 并在获取数据时遇到 orderBy desc function 问题 - I just started with firebase and have problem with orderBy desc function when getting data 从 android firebase 中删除数据 - delete data from android firebase Android 将数据保存到 firebase 数据库 - Android save data to firebase Database 等待 Firebase 异步检索 Android 中的数据 - Wait Firebase async retrieve data in Android Firebase Firestore Query v9 工作“desc”但不是“asc”(索引两者) - Firebase Firestore Query v9 Works "desc" but not "asc" (indexed both) 从实时数据库读取数据 Firebase 并按值排序 - iOS 移动开发 - Swift - Reading data from a Firebase Realtime Database and sorting it by value - iOS Mobile Development- Swift 使用 Android Kotlin 从 Firebase 获取数据 - fetching data from Firebase with Android Kotlin
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM