UPDATE : ขณะนี้มีเอกสารเกี่ยวกับการจัดโครงสร้างข้อมูล นอกจากนี้ยังเห็นโพสต์ที่ยอดเยี่ยมนี้NoSQL โครงสร้างข้อมูล
ปัญหาหลักเกี่ยวกับข้อมูลแบบลำดับชั้นซึ่งตรงข้ามกับ RDBMS คือการดึงดูดข้อมูลแบบซ้อนกันเพราะเราทำได้ โดยทั่วไปคุณต้องการทำให้ข้อมูลเป็นปกติในระดับหนึ่ง (เช่นเดียวกับที่คุณทำกับ SQL) แม้ว่าจะไม่มีคำสั่งเข้าร่วมและแบบสอบถาม
นอกจากนี้คุณยังต้องการที่จะdenormalizeในสถานที่ที่มีประสิทธิภาพในการอ่านเป็นกังวล นี่เป็นเทคนิคที่ใช้โดยแอปขนาดใหญ่ทั้งหมด (เช่น Twitter และ Facebook) และแม้ว่าจะขัดกับหลักการ DRY ของเรา แต่โดยทั่วไปแล้วก็เป็นคุณสมบัติที่จำเป็นของแอปที่ปรับขนาดได้
สาระสำคัญคือคุณต้องการทำงานอย่างหนักในการเขียนเพื่อให้อ่านง่าย เก็บส่วนประกอบทางตรรกะที่อ่านแยกกัน (เช่นสำหรับห้องสนทนาอย่าใส่ข้อความข้อมูลเมตาเกี่ยวกับห้องและรายชื่อสมาชิกทั้งหมดไว้ในที่เดียวกันหากคุณต้องการให้สามารถทำซ้ำกลุ่มได้ในภายหลัง)
ความแตกต่างหลักระหว่างข้อมูลเรียลไทม์ของ Firebase และสภาพแวดล้อม SQL คือการสืบค้นข้อมูล ไม่มีวิธีง่ายๆในการพูดว่า "เลือกผู้ใช้ 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
ด้วย ไม่มีเรื่องใหญ่ถ้าไม่มีสิ่งเหล่านั้นเป็นพัน ๆ แต่เป็นเรื่องใหญ่สำหรับผู้ใช้ 10k ที่มีข้อความมากกว่า 5k ต่อข้อความ
ตอนนี้กลยุทธ์ที่ดีที่สุดสำหรับโครงสร้างตามลำดับชั้นแบบเรียลไทม์จึงชัดเจนยิ่งขึ้น:
/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 อื่นเกี่ยวกับ denormalizing ข้อมูลเพื่อตรวจสอบผู้ออกเช่นกัน ฉันเห็นว่าแฟรงค์โพสต์บทความของ Anant แล้วดังนั้นฉันจะไม่ย้ำตรงนี้ แต่ก็เป็นการอ่านที่ยอดเยี่ยมเช่นกัน