将文档数据检索到documentID与currentUser()。uid相同的List中-Flutter

时间:2020-10-02 12:34:06

标签: firebase flutter google-cloud-firestore firebase-authentication flutter-dependencies

我的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,
      ),
    );
  }
}

谢谢。

1 个答案:

答案 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>