1. Firebase의 Firestore?1. 소개2. 초기 설정1. 프로젝트 생성2. 개발환경 구축2. 데이터 관리1. 데이터 연결2. 데이터 올리기1. document id 지정2. document id 자동 생성3. 데이터 읽기1. 불러오기2. 쿼리4. 데이터 삭제5. 기타
1. Firebase의 Firestore?
1. 소개
- NoSQL 문서 데이터베이스로, 편리하게 DB를 구축하고 관리할 수 있다.
- 데이터는 보통 collection > document > field의 구조를 취하고 있다.
- 데이터에 쿼리를 적용하려면, field에 ArrayUnion을 활용한 배열방식보다는 collection에 document id를 자동 생성해서 올리는 편이 좋다.
- 쿼리를 적용할때는 offset 보다는 start_at, start_after 등의 cursor를 활용하는 것이 리소스 관리에 유리하다.
- 하지만 오프셋이 포함된 쿼리를 보내면 건너뛴 문서마다 읽기 요금이 부과됩니다. 예를 들어 10개의 오프셋을 사용하는 쿼리에서 문서 1개를 반환하면 읽기 11회에 대한 요금이 부과됩니다. 이 같은 추가 비용이 부과되므로 가능하다면 항상 오프셋 대신 커서를 사용해야 합니다. (링크)
2. 초기 설정
1. 프로젝트 생성
- 파이어베이스 콘솔 페이지에서 프로젝트를 추가한다.
- Firestore Database에서
데이터베이스 만들기
버튼을 클릭해서 활성화한다.
- 프로젝트 개요 옆 설정 아이콘 > 프로젝트 설정 > 서비스 계정 페이지에서
새 비공개 키 생성
버튼을 클릭하여, json 파일을 받는다.
2. 개발환경 구축
- firebase_admin 패키지를 설치한다.
pip3 install firebase_admin
2. 데이터 관리
1. 데이터 연결
import firebase_admin from firebase_admin import credentials from firebase_admin import firestore cred = credentials.Certificate('./aiot-converea-firebase-adminsdk-xwmef-81c44db433.json') app = firebase_admin.initialize_app(cred) db = firestore.client()
2. 데이터 올리기
1. document id 지정
- 데이터 생성
doc_ref = db.collection('store').document('information') data = { "location": "seoul", "count": 100, "creation_time": firestore.SERVER_TIMESTAMP, "admin": ["kim", "lee"] } doc_ref.create(data)
- 데이터 수정
doc_ref = db.collection('store').document('information') data = { "count": 150, "admin": firestore.ArrayUnion(["choi"]) } doc_ref.update(data)
2. document id 자동 생성
- 데이터 생성
doc_ref = db.collection('item').document() data = { "name": "mouse", "price": 50000, "manufacture": "logitech" } id = doc_ref.id print(id) # UBxsvI1NSVpsXsJGucg5 doc_ref.set(data)
3. 데이터 읽기
1. 불러오기
- document
doc_ref = db.collection('store').document('information') doc = doc_ref.get() print(doc.to_dict()) # result # {'location': 'seoul', 'creation_time': DatetimeWithNanoseconds(2022, 12, 24, 12, 10, 53, 482000, tzinfo=datetime.timezone.utc), 'count': 150, 'admin': ['kim', 'lee', 'choi']}
- field
doc_ref = db.collection('store').document('information') doc = doc_ref.get(field_paths={"admin"}) print(doc.to_dict()) # result # {'admin': ['kim', 'lee', 'choi']}
2. 쿼리
- offset 활용
ref = db.collection('item') docs = ref.where('price', '>=', 7000).order_by('price').limit(3).offset(1).get() for doc in docs: print(doc.id, doc.to_dict()) # result # rBoTQpeztV7lqHiNxjFt {'manufacture': 'ten', 'price': 12000, 'name': 'clock'} # UBxsvI1NSVpsXsJGucg5 {'name': 'mouse', 'price': 50000, 'manufacture': 'logitech'} # 60W77kc7N6fFeV5SrmLS {'name': 'keyboard', 'price': 80000, 'manufacture': 'thinkway'}
- cursor 활용
ref = db.collection('item') docs = ref.order_by('price').start_at({ "price": 7000 }).get() for doc in docs: print(doc.id, doc.to_dict()) # result # rBoTQpeztV7lqHiNxjFt {'manufacture': 'ten', 'price': 12000, 'name': 'clock'} # UBxsvI1NSVpsXsJGucg5 {'name': 'mouse', 'price': 50000, 'manufacture': 'logitech'} # 60W77kc7N6fFeV5SrmLS {'name': 'keyboard', 'price': 80000, 'manufacture': 'thinkway'}
4. 데이터 삭제
- document
doc_ref = db.collection('item').where('name', '==', 'clock').get() for d in doc_ref: d.reference.delete()
- field
doc_ref = db.collection('store').document('information') doc_ref.update({ 'admin': firestore.ArrayRemove(['lee']), 'location': firestore.DELETE_FIELD })
5. 기타
- 필드의 값에 firestore.SERVER_TIMESTAMP을 적용하려고 하면 에러가 나는데, DatetimeWithNanoseconds 타입으로 올리면 파이어스토어에서 timestamp로 인식된다.
from google.api_core.datetime_helpers import DatetimeWithNanoseconds from zoneinfo import ZoneInfo from datetime import datetime, timezone, timedelta str_time = "2022.12.24 21:05:30" ts = datetime.strptime(str_time, "%Y.%m.%d %H:%M:%S") ts = ts.replace(tzinfo=timezone(timedelta(hours=9))) str_ts = DatetimeWithNanoseconds.fromisoformat(str(ts)) str_ts