使用多个查询过滤数据 flutter firestore

问题描述 投票:0回答:1

我在 firestore 中有一个数据集合,我想按日期和事务类型从中获取数据。
Firestore collection

从该集合中,我想按日期和交易类型过滤数据并将其显示在应用程序中..
Filter RadioButtons screen

在该图像中,我有用于日期选项和交易类型的单选按钮。我创建了一个函数,可以按交易类型过滤数据,但无法按日期过滤。

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

class FilteringScreen extends StatefulWidget {
  @override
  _FilteringScreenState createState() => _FilteringScreenState();
}

class _FilteringScreenState extends State<FilteringScreen> {
  String selectedTransactionType = '';
  DateTime? selectedDateFilter;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Filtering Screen'),
        actions: [
          IconButton(
            icon: Icon(Icons.filter_alt),
            onPressed: () async {
              await _showFilterDialog(context);
            },
          ),
        ],
      ),
      body: _buildStreamBuilder(),
    );
  }

  StreamBuilder<QuerySnapshot> _buildStreamBuilder() {
    CollectionReference transactions = FirebaseFirestore.instance.collection('transaction');

    // Build query based on selected filters
    Query filteredQuery = transactions;

    if (selectedTransactionType.isNotEmpty) {
      filteredQuery = filteredQuery.where('transactionType', isEqualTo: selectedTransactionType);
    }

    if (selectedDateFilter != null) {
      filteredQuery = filteredQuery.where('date', isLessThan: selectedDateFilter);
    }

    return StreamBuilder<QuerySnapshot>(
      stream: filteredQuery.snapshots(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return CircularProgressIndicator();
        }

        if (!snapshot.hasData || snapshot.data == null) {
          return Center(child: Text('No data.'));
        }

        var docs = snapshot.data!.docs;
        if (docs.isEmpty) {
          return Center(child: Text('No filtered data.'));
        }

        return ListView.builder(
          itemCount: docs.length,
          itemBuilder: (context, index) {
            var data = docs[index];
            // Build UI using data
            // ...

            return ListTile(
              title: Text(data['imei']),
              subtitle: Text(data['transactionType']),
            );
          },
        );
      },
    );
  }

  Future<void> _showFilterDialog(BuildContext context) async {
    await showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text('Filter Options'),
          content: Column(
            children: [
              // Add your radio buttons and date picker here
              // Similar to what you did in the FilteringScreen
Row(
            children: [
              Radio(
                value: 'In',
                groupValue: selectedTransactionType,
                onChanged: (value) {
                  setState(() {
                    selectedTransactionType = value.toString();
                  });
                },
              ),
              Text('In'),
              Radio(
                value: 'Out',
                groupValue: selectedTransactionType,
                onChanged: (value) {
                  setState(() {
                    selectedTransactionType = value.toString();
                  });
                },
              ),
              Text('Out'),
               Radio(
                value: '',
                groupValue: selectedTransactionType,
                onChanged: (value) {
                  setState(() {
                    selectedTransactionType = value.toString();
                  });
                },
              ),
              Text('All'),
                         ],
          ),
          // Radio buttons for date filters
          Row(
            children: [
              Radio(
                value: DateTime.now().subtract(Duration(days: 1)),
                groupValue: selectedDateFilter,
                onChanged: (value) {
                  setState(() {
                    selectedDateFilter = DateTime.now().subtract(Duration(days: 1));
                    print(selectedDateFilter);
                  });
                },
              ),
              Text('Today'),
              Radio(
                value:DateTime.now().subtract(Duration(days: 2)),
                groupValue: selectedDateFilter,
                onChanged: (value) {
                  setState(() {
                   selectedDateFilter = DateTime.now().subtract(Duration(days: 2));
                    print(selectedDateFilter);
                  });
                },
              ),
              Text('Yesterday'),
              Radio(
                value: DateTime.now().subtract(Duration(days: 7)),
                groupValue: selectedDateFilter,
                onChanged: (value) {
                  setState(() {
                    selectedDateFilter = DateTime.now().subtract(Duration(days: 7));
                     print(selectedDateFilter);
                  });
                },
              ),
              Text('Week Ago'),
            ],
          ),
              ElevatedButton(
                onPressed: () {
                  Navigator.of(context).pop(); // Close the dialog
                  setState(() {
                    // Update filters based on user selection
                    // You can access the selected values from your radio buttons and date picker
                  });
                },
                child: Text('OK'),
              ),
            ],
          ),
        );
      },
    );
  }
}

当我从日期和交易类型中选择选项时,我收到一些错误

[  +15 ms] W/Firestore(28605): (24.9.1) [Firestore]: Listen for Query(target=Query(transaction where transactionType==In and date<time(1706094811,269000000) order by date, __name__);limitType=LIMIT_TO_FIRST) failed: Status{code=FAILED_PRECONDITION,  description=The query requires an index. You can create it here: https://console.firebase.google.com/v1/r/project/estock-test-f09cb/firestore/indexes?create_composite=ClVwcm9qZWN0cy9lc3RvY2stdGVzdC1mMDljYi9kYXRhYmFzZXMvKGRlZmF1bHQpL2NvbGxlY3Rpb25Hcm91cHMvdHJhbnNhY3Rpb24vaW5kZXhlcy9fEAEaEwoPdHJhbnNhY3Rpb25UeXBlEAEaCAoEZG [ +706 ms] I/flutter (28605): 2024-01-25 19:13:37.670846 [+2405 ms] W/Firestore(28605): (24.9.1) [WatchStream]: (52d638e) Stream closed with status: Status{code=NOT_FOUND, description=Target id not found: 164, cause=null}.

如果我没有从 radioButton 选择任何选项,我希望在 StreamBuilder 中显示完整的集合

database flutter google-cloud-firestore filter
1个回答
0
投票

此错误与 Flutter 无关,与 Firebase 无关。 Firebase 需要为一些高级查询创建索引(例如同时按两个字段进行过滤)。

创建所需索引的最简单方法(如文档建议的那样)是使用返回错误中的链接。从你的错误中我看到它是:

https://console.firebase.google.com/v1/r/project/estock-test-f09cb/firestore/indexes?create_composite=ClVwcm9qZWN0cy9lc3RvY2stdGVzdC1mMDljYi9kYXRhYmFzZXMvKGRlZmF1bHQpL2NvbGxlY3Rpb25Hcm91cHMvdHJhbnNhY3Rpb24vaW5kZXhlcy9fEAEaEwoPdHJhbnNhY3Rpb25UeXBlEAEaCAoEZG

我不知道它们是否过期,如果它们只是尝试运行相同的查询,您将在另一个链接中得到相同的错误。

访问链接后,只需按照说明操作即可,非常简单。

© www.soinside.com 2019 - 2024. All rights reserved.