- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我是 React Native 和 Firebase 的新手,但了解 SQL 关系。我试图了解如何在 NoSQL 中使用 firebase 对多对多关系进行建模。
在我的场景中,用户可以拥有多个组,组可以有多个用户所有者。
我想显示特定用户的组信息(名称、城市状态)。 (在这种情况下,文档编号: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 多对多加入 firebase 实时数据库
但是,这使用了实时数据库而不是我想要使用的文件存储。
我想做同样的事情,但使用:用户、用户组和组
数据的结构是否应该不同?
我在下面实现了 Frank van Puffelen 的回答。它有效,但会带来其他问题。
如果我按照描述使用 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": {
"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
});
});
}
这种方法对我来说似乎更干净。但现在我在根组集合和用户集合下有重复数据。
在这种方法中使用数据库中重复的组数据是否更好?
我有关系数据库背景并学习 NoSQL 最佳实践。我的直觉是不要在数据库中复制数据。
最佳答案
您正在打印 console.log(groups)
outside 加载组的回调。这是行不通的,因为数据是从 Firestore 异步加载的,并且您的日志语句在加载任何数据之前运行。
如果放置一些简单的日志语句,这是最容易看到的:
console.log("Start loading documents");
group_ids.forEach(function (group_id) {
this.groupRef = firebase.firestore().collection('Group').doc(group_id);
this.groupRef.get().then((groupDoc) => {
console.log("Loaded document");
});
});
console.log("Started loading documents");
当您运行这段代码时,它会输出:
Start loading documents
Started loading documents
Loaded document
Loaded document
...
这可能不是您期望的顺序,但它完美地解释了为什么 groups
数组在您打印时为空:尚未加载任何组。事实上,如果您在 then()
回调中记录 groups
,您会看到它一次填充一个文档。
任何需要文档的代码都需要在回调中,或者使用 promise 等待文档加载。由于您正在等待多个文档,请使用 Promise.all()
:
var promises = [];
group_ids.forEach(function (group_id) {
promises.push(firebase.firestore().collection('Group').doc(group_id).get())
});
Promise.all(promises).then(function(docs) {
docs.forEach((groupDoc) => {
group.name = groupDoc._data['name'];
group.city = groupDoc._data['city'];
group.state = groupDoc._data['state'];
groups.push(group);
});
console.log(groups);
});
关于javascript - 如何将数据与 React native 和多对多 firebase firestore 集合关系结合起来?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54774443/
我是一名优秀的程序员,十分优秀!