将文档数据检索到一个列表中,其中 documentID 与 currentUser().uid 相同 - Flutter
Posted
技术标签:
【中文标题】将文档数据检索到一个列表中,其中 documentID 与 currentUser().uid 相同 - Flutter【英文标题】:Retrieving documents data into a List where documentID is the same as currentUser().uid - Flutter 【发布时间】:2021-01-18 03:14:35 【问题描述】:我的 CustomerNotifier 类中有一个函数,它从 Firebase 中读取所有客户作为列表,如下所示:
getCustomers(CustomerNotifier customerNotifier) async
String userId = (await FirebaseAuth.instance.currentUser()).uid;
print('Current logged in user uid is: $userId');
var snapshot = await customerCollection
.orderBy('created_at', descending: true)
.getDocuments();
List<Customer> _customerList = [];
snapshot.documents.forEach((document)
Customer customer = Customer.fromMap(document.data);
_customerList.add(customer);
);
customerNotifier.customerList = _customerList;
我有另一个功能来更新或创建新客户并保存到 Firebase,如下所示:
Future updateCustomer(Customer customer, bool isUpdating) async
CollectionReference customerRef =
await Firestore.instance.collection('customer');
if (isUpdating)
customer.updatedAt = Timestamp.now();
await customerRef.document().updateData(customer.toMap());
print('updated customer with id: $customer.id');
else
customer.createdAt = Timestamp.now();
DocumentReference documentReference =
await customerRef.add(customer.toMap());
customer.id = documentReference.documentID;
print('created customer successfully with id: $customer.id');
await documentReference.setData(customer.toMap(), merge: true);
addCustomer(customer);
notifyListeners();
通过上述两种方法,我曾经成功地读取客户数据并将其写入我的 Firebase。但是,我试图只读取当前登录用户创建和更新的数据。所以来自其他***线程的建议,我被建议将我的customer.id设置为userId,其中userId == currentUser().uid。我可以使用更新版本的 updateCustomer 成功写入我的数据库,如下所示:
Future updateCustomer(Customer customer, bool isUpdating) async
CollectionReference customerRef =
await Firestore.instance.collection('customer');
FirebaseUser user = await FirebaseAuth.instance.currentUser();
String userId = user.uid;
print('Current logged in user uid is: $userId');
if (isUpdating)
customer.updatedAt = Timestamp.now();
await customerRef.document(userId).updateData(customer.toMap());
print('updated customer with id: $customer.id');
else
customer.createdAt = Timestamp.now();
DocumentReference documentReference = await customerRef.document(userId);
// add(customer.toMap());
customer.id = documentReference.documentID;
print('created customer successfully with id: $customer.id');
await documentReference.setData(customer.toMap(), merge: true);
addCustomer(customer);
notifyListeners();
我如何继续从仅由 currentUser() 创建的 firebase 读取客户数据,因为 documentID/customer.id 现在等于 currentUser() 登录的 userId?
这是我迄今为止尝试过的:
getCustomers(CustomerNotifier customerNotifier) async
String userId = (await FirebaseAuth.instance.currentUser()).uid;
print('Current logged in user uid is: $userId');
QuerySnapshot snapshot = await Firestore.instance
.collection('customers')
.where('id', isEqualTo: userId)
.orderBy('created_at', descending: true)
.getDocuments();
List<Customer> _customerList = [];
snapshot.documents.forEach((document)
Customer customer = Customer.fromMap(document.data);
_customerList.add(customer);
);
customerNotifier.customerList = _customerList;
//customer_screen.dart //这使用一个ListView.builder来显示currentUser()创建的所有客户
class CustomersScreen extends StatefulWidget
static String id = 'customers';
@override
_CustomersScreenState createState() => _CustomersScreenState();
class _CustomersScreenState extends State<CustomersScreen>
bool showSpinner = true;
bool _isInit = true;
@override
void initState()
if (_isInit)
showSpinner = true;
else
showSpinner = false;
CustomerNotifier customerNotifier =
Provider.of<CustomerNotifier>(context, listen: false);
customerNotifier.getCustomers(customerNotifier);
super.initState();
@override
Widget build(BuildContext context)
CustomerNotifier customerNotifier = Provider.of<CustomerNotifier>(context);
Future<void> _resfreshList() async
customerNotifier.getCustomers(customerNotifier);
return Scaffold(
drawer: DrawerClass(),
appBar: AppBar(
title: Text(
'All customers',
style: kAppBarTextStyle,
),
backgroundColor: kAppBarColour,
),
floatingActionButton: FloatingActionButton(
onPressed: ()
customerNotifier.currentCustomer = null;
Navigator.of(context)
.push(MaterialPageRoute(builder: (BuildContext context)
return CustomerFormScreen(isUpdating: false);
));
,
child: Icon(Icons.add),
backgroundColor: kThemeIconColour,
),
// body: showSpinner
// ? Center(child: CircularProgressIndicator())
body: RefreshIndicator(
child: Consumer<CustomerNotifier>(
builder: (context, customer, child)
return customer == null
? Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
PaddingClass(bodyImage: 'images/empty.png'),
SizedBox(
height: 20.0,
),
Text(
'You don\'t have any customer',
style: kLabelTextStyle,
),
],
)
: Padding(
padding: const EdgeInsets.only(top: 50.0),
child: ListView.separated(
itemBuilder: (context, int index)
return Card(
margin: EdgeInsets.fromLTRB(20.0, 0.0, 20.0, 0.0),
elevation: 15.0,
color: Colors.white70,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(
height: 100.0,
child: Icon(
FontAwesomeIcons.userCircle,
color: kThemeIconColour,
size: 50.0,
),
),
SizedBox(width: 20.0),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(' $customer.customerList[index].firstName' +
' $customer.customerList[index].lastName'),
SizedBox(
height: 8.0,
),
Text(
' $customer.customerList[index].phoneNumber'),
SizedBox(
height: 8.0,
),
Text(
' $customer.customerList[index].email'),
],
),
GestureDetector(
onTap: ()
customerNotifier.currentCustomer =
customerNotifier.customerList[index];
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context)
return CustomerDetailsScreen();
));
,
child: Icon(
FontAwesomeIcons.caretDown,
color: kThemeIconColour,
),
),
],
),
);
,
separatorBuilder: (BuildContext context, int index)
return SizedBox(
height: 20.0,
);
,
itemCount: customerNotifier.customerList.length,
),
);
,
),
onRefresh: _resfreshList,
),
);
谢谢。
【问题讨论】:
您可以发布您当前尝试检索单个客户数据的代码吗? 我刚刚发布了我尝试过的内容。 我在这里看到的是您有一个名为 Users 的集合,该集合中的文档由 uid 命名。您是否只想获取单个 uid 的信息?如果是这样,那么您希望使用 documentSnapshot。但是,您的函数看起来正在寻找客户的集合 -> 这意味着您可能需要第二个集合,因此它看起来像:客户(集合)-> uid(文档)-> thisUsersItems(集合)跨度> 我正在寻找一系列客户。所以基本上,当前登录用户创建的所有客户。我已经将每个客户文档的 documentId 设置为与 currentUser() uid 相同。我不确定我是否得到你最后评论的后半部分。你能用一个示例/更多解释来解释吗?谢谢。 好的,有道理!执行此操作的方法不止一种,您已根据客户文档中的值选择执行此操作。让我更新我的答案 【参考方案1】:EDIT2: 在此处查看复合查询:https://firebase.google.com/docs/firestore/query-data/queries
特别是本节:
db.collection("cities").where("capital", "==", true)
.get()
.then(function(querySnapshot)
querySnapshot.forEach(function(doc)
// doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data());
);
)
.catch(function(error)
console.log("Error getting documents: ", error);
);
你可以使用这个结构。 'cities' 对您来说是 'customer',而“capital” 是您保存为 userIdWhenYouCreatedThisCustomerDocument 的文档中的字段,而不是 true,您将输入当前的用户 ID。当然,这使用 .then(),您可以这样做或使用 await 将结果分配给变量。
我会注意,您应该在完成此操作时查看文档,特别是考虑到以这种方式执行此操作与按用户 ID 执行子集合。两者都是正确的,但是如果您超越概念证明,您会发现 firestore 中的“where 子句不是过滤器”短语是考虑后一种方法的理由。当然,这最终可能根本不重要。
编辑: 基于新信息
您为什么使用 QuerySnapshot?您(当前)正在为此检索文档快照,因此您可以直接使用它。
或者,您能否发布您的 Firestore 的屏幕截图,并删除敏感数据?我想知道您是否打算将数据存储在用户文档中,例如即时检索查询代码期望编写的内容和您的 upsert 代码交付,而不是将其存储在用户文档中的集合中。 如果是后者,另一个答案中的代码可能对您和您当前的代码更有效,因为它被设置为从集合中读取,而不是从文档中读取。当然,任何一种方法都可以同样有效。问题是,现在您的 upsert 和查询的前半部分正在执行前者,而在检索查询的中途您切换到后者。
我认为您可以将其他问题 (Read data from Firebase created by loggedin user - Flutter) 的答案与文档结合起来,在此处找到您的解决方案。
这使用的 firestore 版本比您正在使用的版本更新,但提供了一个很好的起点。 https://firebase.google.com/docs/firestore/query-data/get-data
例如。
DocumentReference ref =
Firestore.instance.collection('YourCollectionNameInFireStore').document(user.uid);
var temp = await docRef.getDocument();
// do something with the data if you want.. not sure of syntax for old version on
// this, for new version it is .data()
temp.data.<field>
【讨论】:
嗨,斯科特。我刚刚在上面的问题中添加了我的 Firestore 的屏幕截图。 嗨,苏格兰人。我听从了您的建议,还通读了文档以了解其工作原理。我能够写信给 firebase,但似乎我在 READ/getCustomers 中缺少一些东西。我在我的问题中编辑了我的 getCustomers() 函数以反映我当前的实现。它第一次工作,但一旦我刷新/热重启应用程序,我就无法在我的 Listview 屏幕中查看所有客户。 嘿。好的,当然,如果不在那里进行讨论,仍然很难确切地知道发生了什么!但是,如果您说 getCustomers 可以满足您的需求,那听起来像是进步。现在可能需要在问题正文中向我们展示您调用该函数的位置。例如,它是否在构建中? 是的。我已经粘贴了我的 customer-screen.dart 代码。这是我调用 getCustomers() 以显示 customer.id == userId 的所有客户的列表的屏幕。也许这提供了更多的上下文。 我读得很快,我自己并没有使用过 onRefresh,但我想知道同时使用 Consumer 和 refresh 来修改 CustomerNotifier,该 CustomerNotifier 每次构建都会重新构建并可以互换使用。 child: Consumer以上是关于将文档数据检索到一个列表中,其中 documentID 与 currentUser().uid 相同 - Flutter的主要内容,如果未能解决你的问题,请参考以下文章