Py学习  »  NoSql

为NoSQL和Flutter复制SQL联接的FireStore

Jake Anderson • 6 年前 • 1032 次点击  

我意识到,在复制与NoSQL文档数据库(如FireStore)的连接方面存在许多问题,但是我无法找到一个使用FireStore的dart/flutter的彻底解决方案。

我做过一些研究,我觉得在下面的例子中,我会寻找“多对多”的关系(如果这是错误的,请纠正我),因为将来可能需要查看所有的配置文件以及所有的连接。

在FireBase中,我有两个根级别的集合(配置文件和连接):

profile
    > documentKey(Auto Generated)
         > name = "John Smith"
         > uid = "xyc4567"

    > documentKey(Auto Generated)
         > name = "Jane Doe"
         > uid = "abc1234"

    > documentKey(Auto Generated)
         > name = "Kate Dee"
         > uid = "efg8910"



connection
    > documentKey(Auto Generated)
         > type = "friend"
         > profileuid = "abc1234"
         > uid = "xyc4567"

    > documentKey(Auto Generated)
         > type = "family"
         > profileuid = "abc1234"
         > uid = "efg8910"

在本例中,当用户john smith(uid:xyc4567)连接到Jane doe(uid:abc1234)和kate dee(uid:efg8910)时,已假设为该用户创建了“连接”文档。

下面是我要复制的关系SQL,以显示John Smith所连接的配置文件列表:

Select * FROM profile, connection 
WHERE profile.uid = connection.profileuid 
AND profile.uid = "xyc4567"

在flutter my flutter应用程序中,我有一个FireStore查询起点:

stream: Firestore.instance.collection('profile')
.where('uid', isEqualTo: "xyc4567").snapshots(),

显然,它只从一个集合返回。如何加入多对多关系中的集合?

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/30507
 
1032 次点击  
文章 [ 2 ]  |  最新文章 6 年前
Jorge Vieira
Reply   •   1 楼
Jorge Vieira    6 年前

我这样做是为了连接两个colections对象和类别的结果。

我做了两个streambuilders来显示在一个列表中,在第一个列表中,我得到了类别并放入了一个地图,然后我查询了对象,并使用categoryID从地图中获得了类别对象:

StreamBuilder<QuerySnapshot>(
              stream: Firestore.instance
                  .collection('categoryPath')
                  .snapshots(),
              builder: (BuildContext context,
                  AsyncSnapshot<QuerySnapshot> categorySnapshot) {
                //get data from categories

                if (!categorySnapshot.hasData) {
                  return const Text('Loading...');
                }

                //put all categories in a map
                Map<String, Category> categories = Map();
                categorySnapshot.data.documents.forEach((c) {
                  categories[c.documentID] =
                      Category.fromJson(c.documentID, c.data);
                });

                //then from objects

                return StreamBuilder<QuerySnapshot>(
                  stream: Firestore.instance
                      .collection('objectsPath')
                      .where('day', isGreaterThanOrEqualTo: _initialDate)
                      .where('day', isLessThanOrEqualTo: _finalDate)
                      .snapshots(),
                  builder: (BuildContext context,
                      AsyncSnapshot<QuerySnapshot> objectsSnapshot) {
                    if (!objectsSnapshot.hasData)
                      return const Text('Loading...');

                    final int count =
                        objectsSnapshot.data.documents.length;
                    return Expanded(
                      child: Container(
                        child: Card(
                          elevation: 3,
                          child: ListView.builder(
                              padding: EdgeInsets.only(top: 0),
                              itemCount: count,
                              itemBuilder: (_, int index) {
                                final DocumentSnapshot document =
                                    objectsSnapshot.data.documents[index];
                                Object object = Object.fromJson(
                                    document.documentID, document.data);

                                return Column(
                                  children: <Widget>[
                                    Card(
                                      margin: EdgeInsets.only(
                                          left: 0, right: 0, bottom: 1),
                                      shape: RoundedRectangleBorder(
                                        borderRadius: BorderRadius.all(
                                            Radius.circular(0)),
                                      ),
                                      elevation: 1,
                                      child: ListTile(
                                        onTap: () {},
                                        title: Text(object.description,
                                            style: TextStyle(fontSize: 20)),
//here is the magic, i get the category name using the map 
of the categories and the category id from the object
                                        subtitle: Text(
                                          categories[object.categoryId] !=
                                                  null
                                              ? categories[
                                                      object.categoryId]
                                                  .name
                                              : 'Uncategorized',
                                          style: TextStyle(
                                              color: Theme.of(context)
                                                  .primaryColor),
                                        ),

                                      ),
                                    ),
                                  ],
                                );
                              }),
                        ),
                      ),
                    );

我不确定你是想要什么,还是很清楚,但我希望它能帮助你。

Alex Mamo
Reply   •   2 楼
Alex Mamo    6 年前

不幸的是,没有 JOIN 云FireStore或其他NoSQL数据库中的子句。在FireStore中,查询很浅。这意味着它们只从运行查询的集合中获取项。无法在单个查询中从两个顶级集合中获取文档。FireStore不支持一次性跨不同集合的查询。单个查询只能使用单个集合中文档的属性。

所以我能想到的最简单的解决方案是查询数据库以获取 uid 来自的用户 profile 收集。一旦您有了这个ID,就进行另一个数据库调用(在回调中),并从 connection 使用以下查询的集合:

stream: Firestore.instance.collection('connection').where('uid', isEqualTo: "xyc4567").snapshots(),

另一个解决方案是创建名为 连接 在每个用户下添加所有 连接 它下面的对象。这种做法被称为 denormalization 当涉及到火场时,这是一种常见的做法。如果你对noqsl数据库不熟悉,我建议你看这段视频, Denormalization is normal with the Firebase Database 为了更好的理解。它适用于FireBase实时数据库,但同样的规则也适用于云FireStore。

另外,当你复制数据时,有一件事需要记住。以同样的方式添加数据,您需要对其进行维护。换句话说,如果您想要更新/禁止一个项目,您需要在它存在的每一个地方进行更新/禁止。