Android中的Firebase数据描述排序

时间:2015-12-08 13:20:53

标签: android sorting firebase

我正在将数据存储在Firebase存储中。

对象Comment,其属性为timestamp。当我将数据从设备推送到Firebase时,我会使用currentTime填充timestamp并以long数据类型存储。

当我使用firebaseRef.orderByChild("timestamp").limitToLast(15)检索数据时,结果不是按照我的预期排序。

我甚至玩过规则而没有结果:

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

我尝试在timestamp数据类型中存储String,同样的问题。

18 个答案:

答案 0 :(得分:52)

Firebase可以按给定属性按升序对项目进行排序,然后返回前N个项目(limitToFirst())或最后N个项目(limitToLast())。没有办法表明您希望项目按降序排列。

有两种方法可以获得您想要的行为:

  1. 使用Firebase查询获取正确的数据,然后在客户端重新排序

  2. 将具有降序值的字段添加到数据

  3. 对于后一种方法,通常有一个倒置的时间戳。

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

答案 1 :(得分:16)

如果您使用Recycler视图来呈现该数据,我会找到一个很好的解决方案......

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

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

它将反转数据呈现......

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);

答案 2 :(得分:11)

我没有看到任何反转数据的选项。但One Brute的方法是获取数据。

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();
}

答案 3 :(得分:8)

我通过扩展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));
}

}

答案 4 :(得分:4)

@Monet_z_Polski方法,基于

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

对自动更新FirebaseRecyclerView有一个奇怪的影响(PopulateViewHolder不会在实时更改中触发)。因此,最好的选择是使用否定键来索引数据

答案 5 :(得分:1)

public static List<'YourModel>desiredList=new ArrayList<>();

//您的实时数据库查询“ORDERBY”、“Name”或Key等

@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();
 }

答案 6 :(得分:1)

如果您将数组列表传递给 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();
        }
    });

翻转顺序,所以第一个是最后一个,最后一个是第一个我建议在将值放入数据库时​​将其作为 9999999999 然后 -1 用于您想要的任何排序然后使用: 如果您不是按值或子项订购它们。

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

如果你想按一个值排序,这是更好的方法,在 db 中将它初始化为 9999999999,然后为它的值 -1

.orderBy("child_ID") 

firebase 会尝试读取每个数字,例如 1 在 6 之前,但由于第一个数字,10 也会在 6 之前。这就是为什么我以 9999999999 为起始值并相应减小的原因

答案 7 :(得分:1)

这是一个客户端解决方案,它会在填充列表后根据firebase数据库中的特定子项对数据进行排序

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

答案 8 :(得分:1)

基于Himanshus的答案,但我使用的是kotlin,而不是问题中的时间戳,即按分数排序的Im应该是相似的。我不确定firebase是否具有升序或降序功能,但这正是我当前项目无法正常工作的原因。我希望它会在不久的将来对其他人有所帮助。

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()
                }
            }

这对我有用。 编码愉快!

答案 9 :(得分:0)

添加一列,即时间戳,其值为(-1*System.currentTimeMillis()) 并且在获取数据时使用orderByChild("timestamp").limitToFirst(15)orderByChild("timestamp").limitToLast(15)根据您的要求。 由于Firebase没有降序规则,因此以排序的方式获取数据是明智之举。

答案 10 :(得分:0)

这很简单,使用-1,-2,-3等将数据存储在firebase数据库中。现在,数据将在recyclerView中以相反的顺序显示。

-3
-2
-1

答案 11 :(得分:0)

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

答案 12 :(得分:0)

如果您正在网上进行操作,则可以将值推入数组中,然后以相反的顺序打印存储的值。

I want to merge three lines into one, result must to be like:
1 "I want to be merged"
2 "I also want to be merged"

答案 13 :(得分:0)

据我了解,没有降序方法,默认情况下,它只是升序,但您可以手动将其撤消。有关更多信息,请阅读有关实时数据库https://firebase.google.com/docs/database/android/lists-of-data#sorting_and_filtering_data

排序和过滤数据的官方文档。

答案 14 :(得分:0)

按TIMESTAMP对子项进行排序可以使用android.support.v7.util.SortedList

完成
  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也可以与RecyclerView

一起使用

答案 15 :(得分:0)

斯威夫特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
    })

答案 16 :(得分:0)

客户端排序很简单,不需要更多系统资源。 每个数据快照都有previousChildkey字段。如果你想要desc排序,想象previousChildkey是nextChildKey。 以下是我的样本:

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);
    }
  }
}

答案 17 :(得分:-1)

我发现当前的Firebase版本支持降序排序:

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

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

希望有帮助