如何使用React native和多对多Firebase Firestore集合关系来加入数据? [英] How can I join data with React native and a many to many firebase firestore collection relationship?

查看:37
本文介绍了如何使用React native和多对多Firebase Firestore集合关系来加入数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是本机和Firebase的新手,但了解SQL关系.我试图了解如何在NoSQL中使用Firebase建立多对多关系的模型.

在我的情况下,用户可以拥有多个组,而组可以具有多个用户所有者.

我想显示特定用户的组信息(名称,城市所在州).(在这种情况下,文档ID:WQQZ6pcMMgQoTxH9cr2XGaPOq9W2).

这是Firebase文件存储中数据的结构方式:

  {"__collections __":{团体": {"group3":{"city":"Aurora","state":"CO",名称":第三组","__collections __":{}},"group4":{"state":"CO","name":第四组","city":丹佛","__collections __":{}},"group5":{"city":"Aurora","state":"CO",名称":第五组","__collections __":{}}},用户":{"Hm56Zhn9TJP9jVYrzJRqHAB8T8H3":{"last_name":需要","first_name":"Sam","__collections __":{}},"WQQZ6pcMMgQoTxH9cr2XGaPOq9W2":{"last_name":"Smith","first_name":将","__collections __":{}}},用户组":{"F4GubhZKqWcJnHahL0TQTOP62Jj1":{"group3":是的,"group4":是的,"__collections __":{}},"WQQZ6pcMMgQoTxH9cr2XGaPOq9W2":{"group5":是"__collections __":{}}}}} 

这是我的代码:

 导出默认类GroupSelect扩展Component {构造函数(道具){超级(道具);this.userGroupRef = firebase.firestore().collection("UserGroups").doc('WQQZ6pcMMgQoTxH9cr2XGaPOq9W2');this.state = {userGroups:[{uid:"group1",名称:第一组",城市:芝加哥",状态:"IL"},{uid:"group2",名称:第二组",城市:丹佛",状态:"CO"}]}}componentDidMount(){this.userGroupRef.get().then((doc)=> {var obj = doc._data;var group_ids = Object.keys(obj).map(function(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);//未正确填充//this.setState({//userGroups:组//});});}使成为() {返回 (this.state.userGroups.map((userGroup,index)=>(<文本> {userGroup.name}-{userGroup.city},{userGroup.state}</Text>)))}} 

如果我注释掉ComponentDidMount()中的所有内容,则render()会正确显示state.UserGroups的原始内容.但是,当我尝试在ComponentDidMount()中填充数组并重置状态userGroups var时,联接和数组填充的时间出现了问题.

如何最好地做到这一点?

我正在根据以下描述的Firebase联接模式:

或者,也许不是:从此视频中:

...在7:17如果您具有sql背景,这与使用中间表进行联接非常相似"

此处有更多详细信息:

Here is my code:

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>
            ))
        )
    }
}

If I comment out everything in ComponentDidMount(), the render() shows the original contents of state.UserGroups correctly. But, when I try to populate the array in the ComponentDidMount() and reset the state userGroups var, there is a problem with the join and the timing of the population of the array.

How best to do this?

I am patterning this off of how firebase joins are described here: https://www.youtube.com/watch?v=Idu9EJPSxiY


Users, eventAttendees and Events many-to-many join in firebase realtime db

But, this uses the realtime database instead of filestore, which is what I want to use.

I want to do the same but with: Users, UserGroups, and Groups

Should the data be structured differently?


I implemented Frank van Puffelen's answer below. It works but that brings up other questions.

If I use the UserGroups collection as described...

constructor(props) {

    super(props);

    this.userGroupRef = firebase.firestore().collection("UserGroups").doc(firebase.auth().currentUser.uid);

    this.state = {
        userGroups: []
    }
}

...it works, but see possible "issues" below.

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
            });
        });
    });
}

If I restructure data and add a groups collection below 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__": {}
                }
            }
        }
    }
}

Then, code becomes more straightforward.

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
        });

    });

}

This method seems cleaner to me. But now I have duplicate data in a root Group collection and under User collection.

Is it better to do it in this method with duplicate Group data in the db?

I have a relational db background and learning NoSQL best practices. My instinct is not to duplicate data in the db.

解决方案

This video may answer my question. ... at 13:31: "this would probably be duplicate data that would live both in the top-level user object and in this individual review and we'll talk in future videos about the best strategies to keep these kinds of things consistent."

This leads me to believe that I should duplicate the needed group data under the user and not do the joining bit in the client. https://www.youtube.com/watch?v=v_hR4K4auoQ

Or, maybe not: From this video: https://www.youtube.com/watch?v=jm66TSlVtcc

... at 7:17 "If you have a sql background, this is very similar to using an intermediate table for joins"

More details here: https://angularfirebase.com/lessons/firestore-nosql-data-modeling-by-example/#Subcollection-Many-to-Many-Relationships

In the structure above, how would you get all the tweets that a user has liked(hearted) using the hearts table that has the foreign keys with a single query?

这篇关于如何使用React native和多对多Firebase Firestore集合关系来加入数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆