Я новичок, чтобы реагировать на нативный и firebase, но понимаю отношения SQL.Я пытаюсь понять, как смоделировать многие и многие отношения с помощью firebase в NoSQL.
В моем сценарии пользователи могут иметь несколько групп, а группы могут иметь несколько владельцев.
Я хочу отобразитьгрупповая информация (имя, город-штат) для конкретного пользователя.(В этом случае идентификатор документа: WQQZ6pcMMgQoTxH9cr2XGaPOq9W2).
Вот как структурируются данные в хранилище файлов Firebase:
{
"__collections__": {
"Group": {
"group3": {
"city": "Aurora",
"state": "CO",
"name": "Group Three",
"__collections__": {}
},
"group4": {
"state": "CO",
"name": "Group Four",
"city": "Denver",
"__collections__": {}
},
"group5": {
"city": "Aurora",
"state": "CO",
"name": "Group Five",
"__collections__": {}
}
},
"User": {
"Hm56Zhn9TJP9jVYrzJRqHAB8T8H3": {
"last_name": "Sneed",
"first_name": "Sam",
"__collections__": {}
},
"WQQZ6pcMMgQoTxH9cr2XGaPOq9W2": {
"last_name": "Smith",
"first_name": "Will",
"__collections__": {}
}
},
"UserGroups": {
"F4GubhZKqWcJnHahL0TQTOP62Jj1": {
"group3": true,
"group4": true,
"__collections__": {}
},
"WQQZ6pcMMgQoTxH9cr2XGaPOq9W2": {
"group5": true
"__collections__": {}
}
}
}
}
Вот мой код:
export default class GroupSelect extends Component {
constructor(props) {
super(props);
this.userGroupRef = firebase.firestore().collection("UserGroups").doc('WQQZ6pcMMgQoTxH9cr2XGaPOq9W2');
this.state = {
userGroups: [
{
uid: 'group1',
name: 'Group One',
city: 'Chicago',
state: 'IL'
},
{
uid: 'group2',
name: 'Group Two',
city: 'Denver',
state: 'CO'
}
]
}
}
componentDidMount() {
this.userGroupRef.get().then((doc) => {
var obj = doc._data;
var group_ids = Object.keys(obj).map(function (key) {
return key;
});
var groups = [];
var group = {};
group_ids.forEach(function (group_id) {
console.log(group_id);
this.groupRef = firebase.firestore().collection('Group').doc(group_id);
this.groupRef.get().then((groupDoc) => {
group.name = groupDoc._data['name'];
group.city = groupDoc._data['city'];
group.state = groupDoc._data['state'];
groups.push(group);
});
});
console.log(groups); //not populated correctly
// this.setState({
// userGroups: groups
// });
});
}
render() {
return (
this.state.userGroups.map((userGroup, index) => (
<Text>{userGroup.name} - {userGroup.city}, {userGroup.state}</Text>
))
)
}
}
Если я закомментирую все в ComponentDidMount (), то render () правильно отобразит исходное содержимое state.UserGroups.Но, когда я пытаюсь заполнить массив в ComponentDidMount () и сбросить состояние userGroups var, возникает проблема с объединением и временем заполнения массива.
Как лучше всего это сделать?
Я описываю здесь, как здесь описываются объединения в firebase: https://www.youtube.com/watch?v=Idu9EJPSxiY
Пользователи, eventAttendees и Events, многие-ко-многим, объединяются в firebaserealtime db
Но при этом используется база данных реального времени вместо хранилища файлов, что я и хочу использовать.
Я хочу сделать то же самое, но с: Users, UserGroups иГруппы
Должны ли данные структурироваться по-другому?
Я реализовал ответ Фрэнка ван Пуффелена ниже. Это работает, но это поднимает другие вопросы.
Если я использую коллекцию UserGroups, как описано ...
constructor(props) {
super(props);
this.userGroupRef = firebase.firestore().collection("UserGroups").doc(firebase.auth().currentUser.uid);
this.state = {
userGroups: []
}
}
... она работает, но см. Возможные "проблемы" ниже.
componentDidMount() {
this.userGroupRef.get().then((doc) => {
var obj = doc._data;
//get array of group ids
var group_ids = Object.keys(obj).map(function (key) {
return key;
});
let promises = [];
//issue: making singleton database calls for each group id, maybe not good.
group_ids.forEach(function (group_id) {
promises.push(firebase.firestore().collection('Group').doc(group_id).get())
});
let groups = [];
let parentThis = this; //issue: get ref to parent this to set in Promise.all below, kinda weird, maybe not so clear
Promise.all(promises).then(function(docs) {
docs.forEach((groupDoc) => {
let group = {};
group.name = groupDoc._data['name'];
group.city = groupDoc._data['city'];
group.state = groupDoc._data['state'];
groups.push(group);
});
parentThis.setState({
userGroups: groups
});
});
});
}
Если я реструктурирую данные и добавлю коллекцию групп ниже User ...
"User": {
"WQQZ6pcMMgQoTxH9cr2XGaPOq9W2": {
"last_name": "Carter",
"first_name": "Will",
"__collections__": {
"Groups": {
"group1": {
"city": "Chicago",
"state": "IL",
"name": "Group One",
"__collections__": {}
},
"group2": {
"city": "Denver",
"state": "CO",
"name": "Group Two",
"__collections__": {}
}
}
}
}
}
Затем код становится более простым.
constructor(props) {
super(props);
//path: User/WQQZ6pcMMgQoTxH9cr2XGaPOq9W2/Groups
this.userGroupRef = firebase.firestore().collection("User").doc(firebase.auth().currentUser.uid).collection("Groups");
this.state = {
userGroups: []
}
}
componentDidMount() {
this.userGroupRef.get().then((doc) => {
let groups = [];
doc._docs.forEach(function (groupDoc) {
let group = {};
group.name = groupDoc._data['name'];
group.city = groupDoc._data['city'];
group.state = groupDoc._data['state'];
groups.push(group);
});
this.setState({
userGroups: groups
});
});
}
Этот метод кажется мне чище.Но теперь у меня есть дубликаты данных в корневой коллекции Group и в разделе User collection.
Лучше ли делать это в этом методе с дублирующимися данными Group в БД?
У меня есть реляционная БДсправочная информация и изучение лучших практик NoSQL.Мой инстинкт не дублировать данные в БД.