我在 firestore 中有一个数据集合,我想按日期和事务类型从中获取数据。
从该集合中,我想按日期和交易类型过滤数据并将其显示在应用程序中..
在该图像中,我有用于日期选项和交易类型的单选按钮。我创建了一个函数,可以按交易类型过滤数据,但无法按日期过滤。
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 中显示完整的集合
此错误与 Flutter 无关,与 Firebase 无关。 Firebase 需要为一些高级查询创建索引(例如同时按两个字段进行过滤)。
创建所需索引的最简单方法(如文档建议的那样)是使用返回错误中的链接。从你的错误中我看到它是:
https://console.firebase.google.com/v1/r/project/estock-test-f09cb/firestore/indexes?create_composite=ClVwcm9qZWN0cy9lc3RvY2stdGVzdC1mMDljYi9kYXRhYmFzZXMvKGRlZmF1bHQpL2NvbGxlY3Rpb25Hcm91cHMvdHJhbnNhY3Rpb24vaW5kZXhlcy9fEAEaEwoPdHJhbnNhY3Rpb25UeXBlEAEaCAoEZG
我不知道它们是否过期,如果它们只是尝试运行相同的查询,您将在另一个链接中得到相同的错误。
访问链接后,只需按照说明操作即可,非常简单。