适用于层次结构的Firebase安全规则

如何让用户访问层次结构中某个节点以下的任何数据,并使其易于查询?这可以在Firebase中完成,还是我必须抛弃我心爱的Firebase并回到…抱怨…抱怨… RDBMS?

我尝试了两种不同的方式.一个可以轻松查询,但很难限制访问.另一个使得更容易限制访问,但意味着我必须做嵌套循环来聚合我的所有数据.

具体来说,我有一个典型的商业组织:

>公司

>西部地区

>第1分部

>部门1
>部门2

> 2区

>部门3
>部门4

>南部地区

>第3分部

>部门5
>部门6

>公司2
…等等.

在最低(部门)级别,我有订单的数量,我必须汇总.

第一次尝试

数据(非规范化)

{
    "Orders": {
        "UniqueID1": {
            "company": "Company",
            "region": "West Region",
            "division": "Division 1",
            "department": "Department 1",
            "amount": 19.8
        },
        "UniqueID2": {
            "company": "Company",
            "region": "West Region",
            "division": "Division 1",
            "department": "Department 1",
            "amount": 20.1
        },
        ...and so on.
    },
    "Users": {
        "Bob's UID": {
            "departments": {
                "Department 1": true, // Note that these two departments combined are Division 1
                "Department 2": true
            }
        }
    }
}

规则

{
    "Orders": {
        ".indexOn": ["company", "region", "division", "department"],
        ".read":false,
        ".write":false,
        "$order_id": {
            ".read": "root.child('Users').child(auth.uid).child('departments').hasChild(data.child('department').val())"
        }
    }
}

结论

优点

>查询是灵活的,例如:ordersRef.orderByChild(‘division’).equalTo(‘Division 1’).
>查询速度很快.对于200k记录,这在2秒内工作.

缺点

>我不相信我可以用一种结构来限制访问.我根据上面的规则得到permission_denied.我认为这是因为我遇到了“规则不是过滤器,tsk tsk tsk”的问题.

第二次尝试

数据(更加规范化)

{
    "Orders": {
        "Department 1": {
            "UniqueID1": {
                "company": "Company",
                "region": "West Region",
                "division": "Division 1",
                "amount": 19.8
            },
            "UniqueID2": {
                "company": "Company",
                "region": "West Region",
                "division": "Division 1",
                "amount": 20.1
            },
        },
        "Department 2": {...
        ...and so on.
    },
    "Users": {
        "Bob's UID": {
            "departments": {
                "Department 1": true, // Note that these two departments combined are Division 1
                "Department 2": true
            }
        }
    }
}

规则

{
    "Orders": {
        ".read":false,
        ".write":false,
        "$order_id": {
            ".read": "root.child('Users').child(auth.uid).child('departments').hasChild(data.child('department').val())"
        }
    }
}

结论

优点

>我现在可以通过一次阅读一个部门来限制使用安全规则的访问权限.

缺点

>我认为我不能对“Orders / $order_id /”公司,地区或部门进行深度和变量索引,这意味着我必须单独调用每个部门的订单以在更高级别进行汇总.

最佳答案 您的第一个数据结构看似合理.您可以访问您有权访问的特定订单,并且您已经可以找到特定用户的部门列表.

要允许访问(例如)分部的订单,您还需要添加将分部映射到订单ID列表的二级索引:

{
    "Orders": {
        "UniqueID1": {
            "company": "Company",
            "region": "West Region",
            "division": "Division 1",
            "department": "Department 1",
            "amount": 19.8
        },
        "UniqueID2": {
            "company": "Company",
            "region": "West Region",
            "division": "Division 1",
            "department": "Department 1",
            "amount": 20.1
        },
        ...and so on.
    },
    "Users": {
        "Bob's UID": {
            "departments": {
                "Department 1": true, // Note that these two departments combined are Division 1
                "Department 2": true
            }
        }
    },
    "OrdersByDivision": {
        "Division 1": {
            "UniqueID1": true,
            "UniqueID2": true
        }
    }
}

现在,您可以在OrdersByDivision下找到带有方向查找的分部的订单列表,然后循环加载订单:

ref.child('OrdersByDivision/Division 1').on('child_added', function(snapshot) {
    ref.child('Orders').child(snapshot.key).once('value', function(order) {
        console.log(order.val());
    });
});

大多数没有使用Firebase进行Web开发的开发人员担心这种模式会很慢.但鉴于Firebase通过已建立的连接检索项目,实际上这非常快.见Speed up fetching posts for my social network app by using query instead of observing a single event repeatedly

点赞