Flutter 앱 Firebase Realtime Database 데이터 정렬 및 필터링

Firebase Realtime Database에서 데이터를 가져올 때, 정렬 및 필터링 하는 방법을 파이어베이스 공식문서 Android에서 데이터 목록 다루기를 참고하여 정리해 본다.

Realtime Database 정렬

정렬은 다음과 같은 메서드를 제공한다.

  • orderByChild() 지정된 하위 키 또는 중첩된 하위 경로의 값에 따라 결과를 정렬합니다.
  • orderByKey() 하위 키에 따라 결과를 정렬합니다.
  • orderByValue() 하위 값에 따라 결과를 정렬합니다.

테스트 JSON 데이터

테스트를 하기 위한 JSON 데이터는 다음과 같다.

{
  "items" : {
    "item1": {
      "desc": "봉봉",
      "title": "포도",
      "category": "fruit",
      "price": 2000,
      "regdate" : 1744297200000
    },
    "item2": {
      "desc": "우유",
      "title": "바나나",
      "category": "food",
      "price": 4000,
      "regdate" : 1744383600000

    },
    "item3": {
      "desc": "제주",
      "title": "감귤",
      "category": "fruit",
      "price": 2500,
      "regdate" : 1744470000000
    }
  }
}

orderByChild

구조화된 데이터에 특정 필드를 지정하여 정렬 한다. 아래는 items의 각 item에 price로 정렬하여 데이터를 받아오는 코드 이다.

    final dbRef = FirebaseDatabase.instance.ref().child('items');
    final query = dbRef.orderByChild("price");

    query.once().then((DatabaseEvent event) {
      final items = <Item>[];
      final itemlst = event.snapshot.children;
      for (final item in itemlst) {
        final value = item.value as Map;
        print('${item.key} - ${value['title']} : ${value['price']}원');
      }
    });

결과는 다음과 같이 가격순으로 정렬되어 표시된다.

I/flutter (32319): item1 - 포도 : 2000원
I/flutter (32319): item3 - 감귤 : 2500원
I/flutter (32319): item2 - 바나나 : 4000원

orderByChild를 사용하면 지정 하위키를 포함하는 데이터가 다음과 같은 순서로 정렬된다.

  1. 지정 하위키 값이 null인 경우 우선 순위이다. 그 다음에는 false인 하위요소가 그 다음으로 정렬된다. 값이 여러개인 경우에는 key에 따라 사전순으로 정렬된다.
  2. 지정 하위키 값이 true인 하위 요소가 그 다음이고 값이 여러개인 경우 key에 따라 사전순으로 정렬된다.
  3. 숫자값이 있는 하위 요소가 그 다음이고 오름차순으로 정렬된다. 값이 여러개인 경우 key에 따라 사전순으로 정렬된다.
  4. 문자열 하위 요소는 사전순,오름차순으로 정렬된다. 값이 여러개인 경우 key에 따라 사전순으로 정렬된다.
  5. 마지막은 객체이며 키에 따라 사전순, 오름차순으로 정렬된다.

orderByKey

아이템의 키순으로 정렬한다. 아래는 키순으로 정렬하는 코드 이다.

    final ref = FirebaseDatabase.instance.ref().child('items');
    final query = ref.orderByKey();

    query.once().then((event) {
      final children = event.snapshot.children;

      for (final item in children) {
        final key = item.key;
        final value = item.value as Map;
        print('$key - ${value['title']}');
      }
    });

결과는 다음과 같이 아이템 키순으로 정렬되어 표시된다.

I/flutter ( 1508): item1 - 포도
I/flutter ( 1508): item2 - 바나나
I/flutter ( 1508): item3 - 감귤

orderByKey는 다음과 같은 순서로 정렬된다.

  1. 키가 32비트 정수로 파싱될 수 있는 하위요소, 오름차순으로 정렬된다.
  2. 키가 문자열 값인 하위요소, 오름차순(사전순)으로 정렬된다.

orderByValue

하위값에 따라 정렬된다. orderByValue는 값이 단순해야하므로(위 JSON 데이터처럼 복잡한 MAP구조는 안됨) 해당 테스트는 아래 JSON 데이터를 이용했다.

{
  "items" : {
    "item1": 10,
    "item2": 20,
    "item3": 1
  }
}

값에 따라 정렬하는 코드는 다음과 같다.

    final ref = FirebaseDatabase.instance.ref().child('items');
    final query = ref.orderByValue();

    query.once().then((event) {
      final children = event.snapshot.children;

      for (final item in children) {
        final key = item.key;
        final value = item.value;
        print('$key - $value');
      }
    });

결과는 다음과 같이 값에 따라 정렬되어 표시된다.

I/flutter ( 3142): item3 - 1
I/flutter ( 3142): item1 - 10
I/flutter ( 3142): item2 - 20

orderByValue의 정렬방식은 orderByChild과 동일하며 지정한 하위키의 값대신 노드 값이 사용된다는 것만 다르다.

Realtime Database 필터링

필터링을 사용하면 제한 또는 범위 메서드를 정렬 기준 메서드와 조합하여 쿼리를 작성할 수 있다. 정렬기준메서드와 달리 여러 함수를 동시에 사용가능하다(ex: startAt, endAt을 함께 조합해서 사용가능)

  • limitToFirst() 정렬된 결과 목록의 시작 부터 반환할 최대 항목 개수 설정.
  • limitToLast() 정렬된 결과 목록의 끝 부터 반환할 최대 항목 개수 설정.
  • startAt() 선택한 정렬 기준 메서드에 따라 지정된 키 or 값보다 크거나 같은 항목 반환.
  • startAfter() 선택한 정렬 기준 메서드에 따라 지정된 키 or 값보다 큰 항목 반환.
  • endAt() 선택한 정렬 기준 메서드에 따라 지정된 키 or 값보다 작거나 같은 항목 반환.
  • endBefore() 선택한 정렬 기준 메서드에 따라 지정된 키 or 값보다 작은 항목 반환.
  • equalTo() 선택한 정렬 기준 메서드에 따라 지정된 키 or 값과 동일한 항목 반환.

위 orderByChild 예제에서 값이 2,500원인 아이템만 가져오는 코드는 다음과 같다.

final query = dbRef.orderByChild("price").equalTo(2500);

상위 2개의 아이템만 가져오는 코드는 다음과 같다.

final query = dbRef.orderByChild("price").limitToFirst(2);

Leave a Comment