본문 바로가기

유니티

[유니티] Firebase Database에 저장된 값 정렬하기 , 문제 해결

계속해서 firebase database를 이용했을 시, 데이터를 정렬하는 법에 대해 알아보겠다.

firebase database에 정렬할 때 사용하는 함수는 3개가 존재하는데, 그 중 가장 많이 사용되는 것은 OrderByChild()이다.

예를 들어서, 내가 구축한 db의 현재 상황이다.

이를 평범하게 점수만 읽어오면 {40,15,35}라는 값을 받아 올 것이다.

이 때, firebase에서 제공하는 OrderByChild함수를 사용할 경우에는 점수에 따라서 오름차순으로 정렬된 값을 바로 받아올 수 있다.

    void ReadData()
    {
        FirebaseDatabase.DefaultInstance.GetReference("rank").OrderByChild("score")
           .GetValueAsync().ContinueWithOnMainThread(task =>
           {
               if (task.IsFaulted)
               {
                   Debug.Log(task.Exception.Message);
               }
               else if (task.IsCompleted)
               {
                   DataSnapshot snapShot = task.Result;
                  foreach(DataSnapshot snap in snapShot.Children)
                   {
                       Debug.Log(snap.Child("score").Value);
                   }

               }
           });
    }

이런식으로 rank라는 레퍼런스 안에서 score에 따라 정렬된 값을 받아온다면, 출력값은 {15,35,40}이 된다.

여기서 문제점이 있는데, 기본적으로 제공되는 함수는 오직 오름차순으로 정렬을 할 수 밖에 없다.

따라서 만약 내림차순으로 바꾸길 원한다면, 약간의 내용을 추가해주면 된다.

 

struct user
    {       
        public string name;
        public string score;

        public user(string name, string score)
        {
            this.name = name;
            this.score = score;
        }
    }
    void ReadData()
    {
        FirebaseDatabase.DefaultInstance.GetReference("rank").OrderByChild("score")
           .GetValueAsync().ContinueWithOnMainThread(task =>
           {
           if (task.IsFaulted)
           {
               Debug.Log(task.Exception.Message);
           }
           else if (task.IsCompleted)
           {
               DataSnapshot snapShot = task.Result;
               List<user> userList = new List<user>();
               foreach (DataSnapshot snap in snapShot.Children)
               {
                   userList.Add(new user(snap.Child("name").Value.ToString(),snap.Child("score").Value.ToString()));
               }
               for(int i = userList.Count - 1; i >= 0; i--)
                   {
                       Debug.Log("유저이름:" + userList[i].name + " 점수:" + userList[i].score);
                   }
               }
           }
           );
    }

C#내에서 list의 삽입과, 특정 index에서 탐색은 O(1)의 코스트이기 때문에, 정렬하는데 큰 자원 소모 없이 진행이 가능하다.

이렇게 바꾸면 결과를 내림차순으로 받아올 수 있다.

 

내림차순!


사실 구현을 할 때 조금 어려운 부분이 있었는데, 처음에는

    void ReadData()
    {
        FirebaseDatabase.DefaultInstance.GetReference("rank").OrderByChild("score")
           .GetValueAsync().ContinueWithOnMainThread(task =>
           {
           if (task.IsFaulted)
           {
               Debug.Log(task.Exception.Message);
           }
           else if (task.IsCompleted)
           {
                   DataSnapshot snapShot = task.Result;          
                   for(int i = 1; i <= snapShot.ChildrenCount; i++)
                    {
                        Debug.Log(snapShot.Child(i.ToString()).Child("score").Value);
                    }                
      
           });
    }

위와 같은 방식으로 정렬이 될 줄 알았는데, 출력해보니 정렬이 안 된 상태로 계속해서 나왔다.

https://stackoverflow.com/questions/53360330/orderbychild-wont-order-firebase-realtime-database/53363129#53363129

 

OrderByChild wont order, Firebase Realtime Database

I use Firebase Realtime Database. I have the following leaderboard data in the Database: Leaders: 0 Name: Michal Score: 40 1 Name: David ...

stackoverflow.com

위 글을 읽고 child index를 통한 접근은 옳지 않다는 것을 배우게 되었다.