如何使用Flutter从Firestore中的collectionGroups查询数据

对于我在Flutter中构建的应用程序,我试图从Firestore检索登录用户在不同日期的保留时隙列表。我到达了可以在给定日期检索保留时隙的位置(通过对该日期进行硬编码并将其传递给futurebuilder),但是当我尝试从collectionGroup检索数据时,列表视图保持为空(快照没有数据)。现在,作为Flutter的初学者,我发现很难理解如何处理collectionGroup查询,因此,我们将不胜感激!

为了快速概述我的数据库的结构,我在github上提供了两张图片:

图片1:https://github.com/winckles/rooster/blob/master/Schermafbeelding%202019-11-10%20om%2020.08.20.png?raw=true

图片2:https://github.com/winckles/rooster/blob/master/Schermafbeelding%202019-11-10%20om%2020.08.43.png?raw=true

下面我包括了futurebuilder和listview构建器

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';

class TimesTest extends StatefulWidget {
  @override
  _TimesTestState createState() => _TimesTestState();
}

class _TimesTestState extends State<TimesTest> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: MyFutureBuilder(),),);
  }
}

class MyFutureBuilder extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: MyTimes().getMyTimes('${loggedInUser.email}'),builder: (context,Asyncsnapshot snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return Center(
            child: CircularProgressIndicator(
              backgroundColor: Colors.lightBlueaccent,);
        } else if (snapshot.hasData) {
          return ListView.builder(
              padding: EdgeInsets.symmetric(horizontal: 10.0,vertical: 20.0),itemCount: snapshot.data.documents.length,itemBuilder: (BuildContext context,int index) {
                Documentsnapshot user = snapshot.data.documents[index];
                return Padding(
                  padding: EdgeInsets.symmetric(
                    horizontal: 7.0,vertical: 3.0,child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,children: <Widget>[
                      Card(
                        color: Colors.white,child: Container(
                          child: ListTile(
                            onTap: () {},title: Text(
                              user.data['hour'],style: TextStyle(
                                color: Colors.grey[900],subtitle: Text(
                              user.data['reserved'],leading: Icon(
                              Icons.access_time,color: Colors.grey[900],],);
              });
        } else if (snapshot.connectionState == ConnectionState.done &&
            !snapshot.hasData) {
          return Center(
            child: Text('No times found'),);
        } else {
          return Center(
            child: Text('Something else is wrong'),);
        }
      },);
  }
}

这就是我从Firestore获取数据的方式。

import 'package:cloud_firestore/cloud_firestore.dart';

class MyTimes {
  Future getMyTimes(String reserved) async {
    return Firestore.instance
        .collectionGroup('hours')
        .where('reserved',isEqualTo: reserved)
        .getDocuments();
  }
}

我创建了一个索引,其集合ID为“ hours”,集合范围为“ collectionGroup”,现在我的安全规则如下:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read,write: if true;
    }

    match /{path=**}/hours/{document}{
    allow read,write;
    }
  }
}

我已经花了很多小时试图找出答案,所以真的很感谢任何有用的东西!

yangongshang0812 回答:如何使用Flutter从Firestore中的collectionGroups查询数据

意识到我只创建了一个综合索引,而我没有考虑单字段索引豁免

如果您正在寻找使用firebase cli进行此操作的方法,则可以按照以下方式进行操作:

  1. 创建一个名为firestore.indexes.json的文件
{
  "indexes": [],"fieldOverrides": [
    {
      "collectionGroup": "your_sub_collection","fieldPath": "the_field","indexes": [
        {
          "order": "ASCENDING","queryScope": "COLLECTION"
        },{
          "order": "DESCENDING",{
          "arrayConfig": "CONTAINS",{
          "order": "ASCENDING","queryScope": "COLLECTION_GROUP"
        }
      ]
    }
  ]
}

通过这种方式,您将保留集合范围的默认值,并为集合组范围启用ASCENDING

  1. 在您的firebase.json中:
  "firestore": {
    "indexes": "indexes/firestore.indexes.json"
  },
  1. 运行firebase deploy --only firestore:indexes

这将完成工作,最后,您的collectionGroup查询将按预期工作。

希望它可以节省一些时间。

,

在您的示例中,您没有使用collectionGroup查询。您需要为非预留的插槽执行类似Firestore.instance.collectionGroup('hours').where('reserved',isEqualTo: '').getDocuments();的操作。

那么,保留该插槽后,您将在002文档中存储什么?而且为什么不为状态使用诸如布尔值的显式类型呢?这样也更容易。

,

我找到了解决问题的办法;首先,当我删除.where('reserved',isEqualTo: reserved)时,我的快照可以从“小时”中检索所有数据,但是当包含它时它不起作用,因此代码起作用了,但是查询却没有。这是由于Firestore数据库的索引设置所致。我在这里阅读了有关Firestore索引的文档: https://firebase.google.com/docs/firestore/query-data/index-overview?authuser=0#automatic_indexing

意识到我只创建了一个综合索引,而没有考虑单字段索引豁免。我添加了两个豁免:

一个用于收集组“小时”中的“小时”字段,同时检查框的上升和下降,另一个用于收集组“小时”中的“保留”字段,同时检查框的上升和下降。现在可以了!

本文链接:https://www.f2er.com/3127899.html

大家都在问