我的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。但是,我试图仅读取当前登录用户创建和更新的数据。因此,从其他stackoverflow线程的建议中,建议我将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();
}
由于documentID / customer.id现在等于登录的currentUser()的userId,我该如何继续从仅由currentUser()创建的Firebase中读取客户数据?
这是到目前为止我尝试过的事情:
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,
),
);
}
}
谢谢。
答案 0 :(得分: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);
});
您可以使用此结构。 “城市”对您来说是“客户”,“大写”是文档中您另存为userIdWhenYouCreatedThisCustomerDocument的字段,而不是true,而是您当前的用户ID。当然,它使用.then(),您可以这样做或使用await将结果分配给变量。
我会注意到,您在阅读本文档时应仔细阅读文档,尤其是与使用用户ID进行子集合进行这种方式相比。两种方法都是正确的,但是如果您超出概念验证的范围,则在Firestore中会发现短语“ where子句不是过滤器”是考虑使用后一种方法的原因。当然,最后可能根本不重要。
编辑: 根据新信息
为什么要使用QuerySnapshot? (当前)您正在为此获取文档快照,因此可以直接使用它。
或者,您可以发布删除了敏感数据的Firestore屏幕截图吗?我想知道您是否打算将数据存储在用户文档中,就像立即检索查询代码期望按原样编写并且您的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>