从 QuerySnapshot 和 Listview Builder (Flutter & Firebase) 中排除文档

Posted

技术标签:

【中文标题】从 QuerySnapshot 和 Listview Builder (Flutter & Firebase) 中排除文档【英文标题】:Exclude documents from QuerySnapshot and Listview Builder (Flutter & Firebase) 【发布时间】:2021-09-16 06:59:52 【问题描述】:

我在 Firebase 中收到了一系列问题。类别存储在一个数组中。现在我想隐藏特定问题,如果用户选择隐藏它(用户 ID 存储在另一个名为 hidden 的数组中)。这是我尝试过的:

StreamBuilder<QuerySnapshot>(
            stream: FirebaseFirestore.instance
                .collection("question")
                .where('category', arrayContainsAny: [widget.cid])
                .where('hidden', '!=', '$user.uid')
                // also tried where('hidden', isNotEqualTo: [user.uid]) 
                .snapshots(),
            builder: (context, snapshot) 
              return !snapshot.hasData
                  ? Center(child: CircularProgressIndicator())
                  : ListView.builder(
                      scrollDirection: Axis.vertical,
                      shrinkWrap: true,
                      itemCount: snapshot.data!.docs.length,
                      itemBuilder: (context, index) 
                        DocumentSnapshot data = snapshot.data!.docs[index];
                        return QuestionList(
                          de_du: data['de_du'],
                          de_sie: data['de_sie'],
                          de_ich: data['de_ich'],
                          qid: data['id'],
                          en: data['en'],
                          id: data.id,
                          documentSnapshot: data,
                        );
                      ,
                    );
            ,
          ),

关于如何到达那里有什么建议吗?

更新:

我尝试实现转换。我仍然遇到错误并且无法正常工作。我得到的错误:transform 中的第一个快照未定义。在变换中的第一个快照之后需要一个 )。我还得到了信息,即未使用用户(用户 ID 的提供者)。

class _CategoryDetailState extends State<CategoryDetail> 
  
  @override
  Widget build(BuildContext context) 
    var user = Provider.of<AuthProvider>(context);
    return Scaffold(
      appBar: AppBar(
        title: Text(
          this.widget.titel,
          style: TextStyle(fontFamily: 'Gruppo'),
        ),
      ),
      body: ListView(
        children: [
          Card(
            margin: EdgeInsets.all(10),
            child: Column(
              children: [
                Image.network(this.widget.image),
                ListTile(
                  title: Text(this.widget.titel),
                  subtitle: Text(this.widget.description),
                ),
              ],
            ),
          ),
          Center(
            child: Text(
              'Fragenübersicht:',
              style: TextStyle(fontFamily: 'Caveat', fontSize: 25),
            ),
          ),
          StreamBuilder<List<DocumentSnapshot>>(
            stream: FirebaseFirestore.instance
                .collection("question")
                .where('category', arrayContainsAny: [widget.cid])
                .snapshots()
                .transform(snapshot => snapshot.docs.where(d => doc.data().hidden.contains(user.userid).toList())),
            builder: (context, snapshot) 
              if (!snapshot.hasData) 
                return Center(child: CircularProgressIndicator());
               else 
                return ListView.builder(
                  scrollDirection: Axis.vertical,
                  physics: ClampingScrollPhysics(),
                  shrinkWrap: true,
                  itemCount: snapshot.data!.length,
                  itemBuilder: (context, index) 
                    DocumentSnapshot data = snapshot.data![index];
                    return QuestionList(
                      de_du: data['de_du'],
                      de_sie: data['de_sie'],
                      de_ich: data['de_ich'],
                      qid: data['id'],
                      en: data['en'],
                      id: data.id,
                      documentSnapshot: data,
                    );
                  ,
                );
              
            ,
          ),
        ],
      ),
    );
  

【问题讨论】:

【参考方案1】:

无法通过条件从Firestore query 中排除单个项目。您需要的是 array-does-not-contain 条件,它不存在。

这意味着您必须从数据库中读取其他项目,然后使用以下内容将它们从流中排除:

StreamBuilder<List<DocumentSnapshot>>(
  stream: FirebaseFirestore.instance
    .collection("question")
    .where('category', arrayContainsAny: [widget.cid])
    .where('hidden', '!=', '$user.uid')
    .snapshots()
    .transform(snapshot => snapshot.docs.where(d => doc.data().hidden.contains(user.uid)).toList(),

您还需要更新构建器以反映它现在获得List&lt;DocumentSnapshot&gt; 而不是QuerySnapshot

【讨论】:

感谢您的回复!因为我对这个很陌生——我仍然没有让它工作..我使用一个列表来完成排除,但我不明白它是如何工作的。如果我得到以下流: stream: FirebaseFirestore.instance .collection("question") .where('category', arrayContainsAny: [widget.cid]) .where('hidden', arrayContainsAny: [user.uid]) 。 snapshots(),.transform() 是如何工作的 List = (data from category-where) - (data from hidden-where) 试图在网上找到更多但没有运气。 transform 调用将您从 Firestore 获得的 Stream&lt;QuerySnapshot&gt; 转换为 Stream&lt;List&lt;DocumentSnapshot&gt;&gt; 并过滤与 UID 不匹配的文档 doc.data().hidden.contains(user.uid) 我还没有让它工作..首先解决其他挑战..这是我列表中的下一个..将再试一次以完成您已经提供的帮助并会尽快回复您;) 嘿弗兰克,我尝试实现转换。我仍然遇到错误并且无法正常工作。我得到的错误:transform 中的第一个快照未定义。在变换的第一个快照之后需要一个 )。我还得到了信息,即未使用用户(用户 ID 的提供者)。

以上是关于从 QuerySnapshot 和 Listview Builder (Flutter & Firebase) 中排除文档的主要内容,如果未能解决你的问题,请参考以下文章

错误:“QuerySnapshot”类没有实例获取器“数据”

Stream<QuerySnapshot> 返回空文档

我是不是需要取消 Stream<QuerySnapshot> (颤振)

Flutter/Firestore:“QuerySnapshot”类没有实例获取器“document”

达到 limit() 后 QuerySnapshot 删除数据

java 为listvie实现基础适配器