답변:
업데이트 : 이제 데이터 구조화에 대한 문서가 있습니다 . 또한 NoSQL 데이터 구조 에 대한이 훌륭한 게시물을 참조하십시오 .
RDBMS와 달리 계층 적 데이터의 주요 문제는 데이터를 중첩 할 수 있기 때문에 데이터를 중첩하려는 유혹이 있다는 것입니다. 일반적으로 조인 문 및 쿼리가 없음에도 불구하고 SQL에서와 마찬가지로 데이터를 어느 정도 정규화하려고합니다.
또한 읽기 효율성이 중요한 곳에서 비정규 화 를 원합니다 . 이는 모든 대규모 앱 (예 : Twitter 및 Facebook)에서 사용하는 기술이며 DRY 원칙에 위배되지만 일반적으로 확장 가능한 앱의 필수 기능입니다.
여기서 요점은 읽기를 쉽게 만들기 위해 열심히 쓰기를 원한다는 것입니다. 개별적으로 읽는 논리적 구성 요소를 별도로 보관합니다 (예 : 채팅방의 경우 메시지, 방에 대한 메타 정보 및 구성원 목록을 모두 같은 위치에 두지 마십시오. 나중에 그룹을 반복 할 수 있도록하려는 경우).
Firebase의 실시간 데이터와 SQL 환경의 주요 차이점은 데이터 쿼리입니다. 데이터의 실시간 특성으로 인해 "SELECT USERS WHERE X = Y"라고 말할 수있는 간단한 방법은 없습니다 (동기화 된 클라이언트를 확인하기 위해 더 간단한 내부 모델이 필요한 지속적으로 변경, 분할, 조정 등).
간단한 예는 아마도 당신을 올바른 마음 상태로 만들 것입니다.
/users/uid
/users/uid/email
/users/uid/messages
/users/uid/widgets
이제 계층 구조이므로 사용자의 이메일 주소를 반복하려면 다음과 같이합니다.
// I could also use on('child_added') here to great success
// but this is simpler for an example
firebaseRef.child('users').once('value')
.then(userPathSnapshot => {
userPathSnapshot.forEach(
userSnap => console.log('email', userSnap.val().email)
);
})
.catch(e => console.error(e));
이 방법의 문제는 난 그냥 사용자의 모든 다운로드 할 수있는 클라이언트 강제 것입니다 messages
및 widgets
도합니다. 수천 개에 해당하는 것이 하나도 없다면 별일 없을 것입니다. 그러나 각각 5k 이상의 메시지를 가진 10k 사용자에게는 큰 문제입니다.
따라서 이제 계층 적 실시간 구조를위한 최적의 전략이 더욱 분명해졌습니다.
/user_meta/uid/email
/messages/uid/...
/widgets/uid/...
이 환경에서 매우 유용한 추가 도구는 인덱스입니다. 특정 속성을 가진 사용자의 인덱스를 생성함으로써 간단히 인덱스를 반복하여 SQL 쿼리를 빠르게 시뮬레이션 할 수 있습니다.
/users_with_gmail_accounts/uid/email
이제 Gmail 사용자를위한 메시지를 받고 싶다면 다음과 같이 할 수 있습니다.
var ref = firebase.database().ref('users_with_gmail_accounts');
ref.once('value').then(idx_snap => {
idx_snap.forEach(idx_entry => {
let msg = idx_entry.name() + ' has a new message!';
firebase.database().ref('messages').child(idx_entry.name())
.on(
'child_added',
ss => console.log(msg, ss.key);
);
});
})
.catch(e => console.error(e));
데이터 비정규 화에 대한 다른 SO 게시물에서 몇 가지 세부 정보를 제공 했으므로 이들도 확인하십시오 . Frank가 이미 Anant의 기사를 게시 한 것을 보았습니다. 그래서 여기서 반복하지는 않겠습니다.
중포 기지 아주 많이 하지 관계형 데이터베이스처럼. 무엇과 비교하고 싶다면 계층 적 데이터베이스와 비교하겠습니다.
Anant는 최근 Firebase 블로그에 데이터 비정규 화에 대한 훌륭한 게시물을 작성했습니다. https://www.firebase.com/blog/2013-04-12-denormalizing-is-normal.html
각 지원자의 자녀로서 각 지원서의 "ID"를 유지하는 것이 좋습니다.
귀하의 시나리오는 관계형 세계에서 일대 다처럼 보입니다. 귀하의 예에 따라 신청자는 많은 응용 프로그램을 가지고 있습니다. firebase nosql 방식으로 오면 아래와 같습니다. 성능 문제없이 확장되어야합니다. 그렇기 때문에 아래에 언급 된 비정규 화가 필요합니다.
applicants:{
applicant1:{
.
.
applications:{
application1:true,
application3:true
}
},
applicant2:{
.
.
applications:{
application2:true,
application4:true
}
}}
applications:{
application1:{
.
.
},
application2:{
.
.
},
application3:{
.
.
},
application4:{
.
.
}}