从 Firebase 集合中删除文档

huangapple go评论126阅读模式
英文:

Delete a document from firebase collection

问题

以下是代码的翻译部分:

我正在开发一个简单的预约应用程序。
对于每个已预约的时间段,我有一个“取消”按钮,按下该按钮后,预约应该从集合中删除。

Future deleteAppt() async {
  QuerySnapshot querySnapshot =
      await FirebaseFirestore.instance.collection("client_bookings").get();

  for (int i = 0; i < querySnapshot.docs.length; i++) {
    var a = querySnapshot.docs[i];

    final collection =
        FirebaseFirestore.instance.collection('client_bookings');
    collection
        .doc(a.id) // <-- 要删除的文档 ID。
        .delete() // <-- 删除
        .then((_) => print('已删除'))
        .catchError((error) => print('删除失败:$error'));

    print(a.id);
  }
}

到目前为止,这是我的代码。但是,当点击按钮时,所有预约都被删除。您能给我一些建议,我如何修复这个问题吗?

此外,我正在使用StreamBuilder和ListView.builder来迭代集合并在容器中显示每个预约。

StreamBuilder(
  stream: FirebaseFirestore.instance
      .collection('client_bookings')
      .where("email",
          isEqualTo: FirebaseAuth.instance.currentUser?.email)
      .snapshots(),
  builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
    if (snapshot.hasError) {
      print(snapshot.hasData);
      return Text("错误");
    } else if (snapshot.hasData) {
      print(snapshot.hasData);
      return ListView.builder(
          itemCount: snapshot.data?.docs.length,
          shrinkWrap: true,
          physics: NeverScrollableScrollPhysics(),
          itemBuilder: (context, int i) {
            var data = snapshot.data!.docs[i];
            var bookingStart = data['bookingStart'];
            DateTime bookingStartConverted = DateTime.parse(bookingStart);

            if (bookingStartConverted.isAfter(today)) {
              print("即将到来");
              return Container(
                // 这里是容器的描述和构建
                // ...
              );
            } else {
              print("没有预约");
            }
          });
    } else {
      return Text("其他情况");
    }
  }
)

// 取消预约对话框

class CancelApptBox extends StatelessWidget {
  const CancelApptBox({super.key});

  Future deleteAppt() async {
    QuerySnapshot querySnapshot =
        await FirebaseFirestore.instance.collection("client_bookings").get();

    for (int i = 0; i < querySnapshot.docs.length; i++) {
      var a = querySnapshot.docs[i];

      final collection =
          FirebaseFirestore.instance.collection('client_bookings');
      collection
          .doc(a.id) // <-- 要删除的文档 ID。
          .delete() // <-- 删除
          .then((_) => print('已删除'))
          .catchError((error) => print('删除失败:$error'));

      print(a.id);
    }
  }

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      title: const Text('您确定要取消预约吗?'),
      actions: <Widget>[
        TextButton(
          onPressed: () {
            Navigator.pop(context, '是的');
            deleteAppt();
          },
          child: const Text('是的',
              style: TextStyle(fontWeight: FontWeight.bold)),
        ),
        TextButton(
          onPressed: () => Navigator.pop(context, '返回'),
          child: const Text('返回'),
        ),
      ],
    );
  }
}

希望这些翻译对您有所帮助。如果您有任何进一步的问题,欢迎提出。

英文:

I am working on a simple booking application.
For each booked slot I have a Cancel button, when pressed the appointment should be deleted from the collection.

  Future deleteAppt() async {
    QuerySnapshot querySnapshot =
        await FirebaseFirestore.instance.collection(&quot;client_bookings&quot;).get();

    for (int i = 0; i &lt; querySnapshot.docs.length; i++) {
      var a = querySnapshot.docs[i];

      final collection =
          FirebaseFirestore.instance.collection(&#39;client_bookings&#39;);
      collection
          .doc(a.id) // &lt;-- Doc ID to be deleted.
          .delete() // &lt;-- Delete
          .then((_) =&gt; print(&#39;Deleted&#39;))
          .catchError((error) =&gt; print(&#39;Delete failed: $error&#39;));

      print(a.id);
    }
  }

This is my code so far. However, when the button is clicked all appointments are deleted. Could you give me any advice how can i fix this?
In addition, I am using a StreamBuilder and ListView.builder to iterate though the collection and display each appointment in a container.

scheme image added

StreamBuilder(
stream: FirebaseFirestore.instance
.collection(&#39;client_bookings&#39;)
.where(&quot;email&quot;,
isEqualTo: FirebaseAuth.instance.currentUser?.email)
.snapshots(),
builder: (context, AsyncSnapshot&lt;QuerySnapshot&gt; snapshot) {
if (snapshot.hasError) {
print(snapshot.hasData);
return Text(&quot;error&quot;);
} else if (snapshot.hasData) {
print(snapshot.hasData);
return ListView.builder(
itemCount: snapshot.data?.docs.length,
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, int i) {
var data = snapshot.data!.docs[i];
var bookingStart = data[&#39;bookingStart&#39;];
DateTime bookingStartConverted = DateTime.parse(bookingStart);
if(bookingStartConverted.isAfter(today)) {
print(&quot;upcoming&quot;);
return Container(
height: height,
width: width,
margin: EdgeInsets.symmetric(
horizontal: 10, vertical: 10),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(
20),
boxShadow: [
BoxShadow(
color: Colors.blueGrey
.shade100,
blurRadius: 5,
spreadRadius: 3)
]),
child: Align(
alignment: Alignment.center,
child: Column(children: [
Padding(
padding:
EdgeInsets.only(
left: 15, top: 8),
child: Text(
&quot;Dr. &quot; + data[&#39;doctorName&#39;],
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight
.bold,
color: Colors
.blueAccent),
)),
Padding(
padding: EdgeInsets.only(
top: 5),
child: Text(
data[&#39;doctorType&#39;],
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 15,
color: Colors.grey),
)),
const Divider(
height: 22,
thickness: 0.4,
color: Colors.grey,
),
Row(
children: [
Icon(Icons
.access_time_outlined),
Expanded(
flex: 1,
child: Text(
data[&#39;bookingStart&#39;],
style: TextStyle(
fontSize: 16,
color: Colors
.black87
.withOpacity(
0.5)),
)),
Icon(Icons
.location_on_outlined),
Expanded(
flex: 1,
child: TextButton(
onPressed: () {
opentApptMap();
},
child: Text(
data[&#39;hospitalName&#39;],
textAlign: TextAlign
.center,
style: TextStyle(
decoration: TextDecoration
.underline),
)),
)
],
),
Padding(
padding:
const EdgeInsets.only(
top: 5.0),
child: Row(
children: &lt;Widget&gt;[
Expanded(
child: SizedBox(
// width: 80,
height: 30,
child: ElevatedButton(
child: const Text(
&quot;Cancel&quot;),
onPressed: () {
Navigator.of(
context).push(
MaterialPageRoute(
builder: (
context) =&gt;
CancelApptBox()));
},
style:
ElevatedButton
.styleFrom(
shape:
StadiumBorder(),
textStyle: TextStyle(
fontSize: 15,
)),
),
),
),
Padding(
padding:
EdgeInsets.only(
right: 8)),
Expanded(
child: SizedBox(
// width: 80,
height: 30,
child: ElevatedButton(
child:
const Text(
&quot;Reschedule&quot;),
onPressed: () {},
style:
ElevatedButton
.styleFrom(
shape:
StadiumBorder(),
textStyle: TextStyle(
fontSize: 15,
)),
),
),
)
],
))
])),
);
}else{
print(&quot;no appts&quot;);
}
});
} else {
return Text(&quot;else&quot;);
}
})

//Cancel appt Box

class CancelApptBox extends StatelessWidget {
const CancelApptBox({super.key});
Future deleteAppt() async {
QuerySnapshot querySnapshot =
await FirebaseFirestore.instance.collection(&quot;client_bookings&quot;).get();
for (int i = 0; i &lt; querySnapshot.docs.length; i++) {
var a = querySnapshot.docs[i];
final collection =
FirebaseFirestore.instance.collection(&#39;client_bookings&#39;);
collection
.doc(a.id) // &lt;-- Doc ID to be deleted.
.delete() // &lt;-- Delete
.then((_) =&gt; print(&#39;Deleted&#39;))
.catchError((error) =&gt; print(&#39;Delete failed: $error&#39;));
print(a.id);
}
}
@override
Widget build(BuildContext context) {
return AlertDialog(
title: const Text(&#39;Are you sure you want to cancel the appointment?&#39;),
actions: &lt;Widget&gt;[
TextButton(
onPressed: () {
Navigator.pop(context, &#39;Yes&#39;);
deleteAppt();
},
child: const Text(&#39;Yes&#39;,
style: TextStyle(fontWeight: FontWeight.bold)),
),
TextButton(
onPressed: () =&gt; Navigator.pop(context, &#39;Go back&#39;),
child: const Text(&#39;Go back&#39;),
),
],
);
}
}

从 Firebase 集合中删除文档

答案1

得分: 2

如果您想要删除特定的预约,您应该传递预约 ID。

Future<void> deleteAppt(String apptId) async {
  final collection = FirebaseFirestore.instance.collection('client_bookings');
  try {
    await collection.doc(apptId).delete();
    print('已删除');
  } catch (error) {
    print('删除失败:$error');
  }
}
英文:

If you want to delete a specific appointment, you should pass appointment id.

Future&lt;void&gt; deleteAppt(String apptId) async {
  final collection = FirebaseFirestore.instance.collection(&#39;client_bookings&#39;);
  try {
    await collection.doc(apptId).delete();
    print(&#39;Deleted&#39;);
  } catch (error) {
    print(&#39;Delete failed: $error&#39;);
  }
}

答案2

得分: 0

你正在迭代每个文档并删除该文档

 for (int i = 0; i &lt; querySnapshot.docs.length; i++) {}

删除for语句

取消按钮

class CancelApptBox extends StatelessWidget {
  int i;
  const CancelApptBox({super.key,}this.i);

  Future deleteAppt() async {
    QuerySnapshot querySnapshot =
        await FirebaseFirestore.instance.collection(&quot;client_bookings&quot;).get();

      var a = querySnapshot.docs[i];

      final collection =
          FirebaseFirestore.instance.collection(&#39;client_bookings&#39;');
      collection
          .doc(a.id) // &lt;-- 要删除的文档ID
          .delete() // &lt;-- 删除
          .then((_) =&gt; print(&#39;已删除&#39;))
          .catchError((error) =&gt; print(&#39;删除失败:$error&#39;));

      print(a.id);
    
  }

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      title: const Text(&#39;您确定要取消预约吗?&#39;),
      actions: &lt;Widget&gt;[
        TextButton(
          onPressed: () {
            Navigator.pop(context, &#39;是的&#39;);
            deleteAppt();
          },
          child: const Text(&#39;是的&#39;,
              style: TextStyle(fontWeight: FontWeight.bold)),
        ),
        TextButton(
          onPressed: () =&gt; Navigator.pop(context, &#39;返回&#39;),
          child: const Text(&#39;返回&#39;),
        ),
      ],
    );
  }
}

主页

StreamBuilder(
    stream: FirebaseFirestore.instance
        .collection(&#39;client_bookings&#39;)
        .where(&quot;email&quot;,
            isEqualTo: FirebaseAuth.instance.currentUser?.email)
        .snapshots(),
    builder: (context, AsyncSnapshot&lt;QuerySnapshot&gt; snapshot) {
        if (snapshot.hasError) {
            print(snapshot.hasData);
            return Text(&quot;错误&quot;);
        } else if (snapshot.hasData) {
            print(snapshot.hasData);
            return ListView.builder(
                itemCount: snapshot.data?.docs.length,
                shrinkWrap: true,
                physics: NeverScrollableScrollPhysics(),
                itemBuilder: (context, int i) {
                    var data = snapshot.data!.docs[i];
                    var bookingStart = data[&#39;bookingStart&#39;];
                    DateTime bookingStartConverted = DateTime.parse(bookingStart);
                    
                    if(bookingStartConverted.isAfter(today)) {
                        print(&quot;即将到来&quot;);
                        return Container(
                            height: height,
                            width: width,
                            margin: EdgeInsets.symmetric(
                                horizontal: 10, vertical: 10),
                            decoration: BoxDecoration(
                                color: Colors.white,
                                borderRadius: BorderRadius.circular(
                                    20),
                                boxShadow: [
                                    BoxShadow(
                                        color: Colors.blueGrey
                                            .shade100,
                                        blurRadius: 5,
                                        spreadRadius: 3)
                                ]),
                            child: Align(
                                alignment: Alignment.center,
                                child: Column(children: [
                                    Padding(
                                        padding:
                                        EdgeInsets.only(
                                            left: 15, top: 8),
                                        child: Text(
                                            &quot;Dr. &quot; + data[&#39;doctorName&#39;],
                                            textAlign: TextAlign.left,
                                            style: TextStyle(
                                                fontSize: 17,
                                                fontWeight: FontWeight
                                                    .bold,
                                                color: Colors
                                                    .blueAccent),
                                        )),
                                    Padding(
                                        padding: EdgeInsets.only(
                                            top: 5),
                                        child: Text(
                                            data[&#39;doctorType&#39;],
                                            textAlign: TextAlign.left,
                                            style: TextStyle(
                                                fontSize: 15,
                                                color: Colors.grey),
                                        )),
                                    const Divider(
                                        height: 22,
                                        thickness: 0.4,
                                        color: Colors.grey,
                                    ),
                                    Row(
                                        children: [
                                            Icon(Icons
                                                .access_time_outlined),
                                            Expanded(
                                                flex: 1,
                                                child: Text(
                                                    data[&#39;bookingStart&#39;],
                                                    style: TextStyle(
                                                        fontSize: 16,
                                                        color: Colors
                                                            .black87
                                                            .withOpacity(
                                                            0.5)),
                                                )),
                                            Icon(Icons
                                                .location_on_outlined),
                                            Expanded(
                                                flex: 1,
                                                child: TextButton(
                                                    onPressed: () {
                                                        opentApptMap();
                                                    },
                                                    child: Text(
                                                        data[&#39;hospitalName&#39;],
                                                        textAlign: TextAlign
                                                            .center,
                                                        style: TextStyle(
                                                            decoration: TextDecoration
                                                                .underline),
                                                    )),
                                            )
                                        ],
                                    ),
                                    Padding(
                                        padding:
                                        const EdgeInsets.only(
                                            top: 5.0),
                                        child: Row(
                                            children: &lt;Widget&gt;[
                                                Expanded(
                                                    child: SizedBox(
                                                        // width: 80,
                                                        height: 30,
                                                        child: ElevatedButton(
                                                            child: const Text(
                                                                &quot;取消&quot;),
                                                            onPressed: () {
                                                                Navigator.of(
                                                                    context).push(
                                                                    MaterialPageRoute(
                                                                        builder: (
                                                                            context) =&gt;
                                                                            CancelApptBox(i)));
                                                            },
                                                            style:
                                                            ElevatedButton
                                                                .styleFrom(
                                                                shape:
                                                                StadiumBorder(),
                                                                textStyle: TextStyle(
                                                                    fontSize: 15,
                                                                ))),
                                                    ),
                                                ),
                                                Padding(
                                                    padding:
                                                    EdgeInsets.only(
                                                        right: 8)),
                                                Expanded(
                                                    child: SizedBox(
                                                        // width: 80,
                                                        height: 30,
                                                        child: ElevatedButton(
                                                            child:
                                                            const Text(
                                                                &quot;重新预约&quot;),
                                                            onPressed: () {},
                                                            style:
                                                            ElevatedButton
                                                                .styleFrom(
                                                                shape:
                                                                StadiumBorder(),
                                                                textStyle: TextStyle(
                                                                    fontSize: 15,
                                                                ))),
                                                    ),
                                                )
                                            ],
                                        ))
                                ])),
                        );
                    }else{
                        print(&quot;没有预约&quot;);
                    }
                });
        } else {
            return Text(&quot;其他情况&quot;);
        }
    })
英文:

you are iterating over every document and deleting that document

 for (int i = 0; i &lt; querySnapshot.docs.length; i++) {}

remove the for statement

cancel button

class CancelApptBox extends StatelessWidget {
int i;
const CancelApptBox({super.key,}this.i);
Future deleteAppt() async {
QuerySnapshot querySnapshot =
await FirebaseFirestore.instance.collection(&quot;client_bookings&quot;).get();
var a = querySnapshot.docs[i];
final collection =
FirebaseFirestore.instance.collection(&#39;client_bookings&#39;);
collection
.doc(a.id) // &lt;-- Doc ID to be deleted.
.delete() // &lt;-- Delete
.then((_) =&gt; print(&#39;Deleted&#39;))
.catchError((error) =&gt; print(&#39;Delete failed: $error&#39;));
print(a.id);
}
@override
Widget build(BuildContext context) {
return AlertDialog(
title: const Text(&#39;Are you sure you want to cancel the appointment?&#39;),
actions: &lt;Widget&gt;[
TextButton(
onPressed: () {
Navigator.pop(context, &#39;Yes&#39;);
deleteAppt();
},
child: const Text(&#39;Yes&#39;,
style: TextStyle(fontWeight: FontWeight.bold)),
),
TextButton(
onPressed: () =&gt; Navigator.pop(context, &#39;Go back&#39;),
child: const Text(&#39;Go back&#39;),
),
],
);
}
}

main page

StreamBuilder(
stream: FirebaseFirestore.instance
.collection(&#39;client_bookings&#39;)
.where(&quot;email&quot;,
isEqualTo: FirebaseAuth.instance.currentUser?.email)
.snapshots(),
builder: (context, AsyncSnapshot&lt;QuerySnapshot&gt; snapshot) {
if (snapshot.hasError) {
print(snapshot.hasData);
return Text(&quot;error&quot;);
} else if (snapshot.hasData) {
print(snapshot.hasData);
return ListView.builder(
itemCount: snapshot.data?.docs.length,
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, int i) {
var data = snapshot.data!.docs[i];
var bookingStart = data[&#39;bookingStart&#39;];
DateTime bookingStartConverted = DateTime.parse(bookingStart);
if(bookingStartConverted.isAfter(today)) {
print(&quot;upcoming&quot;);
return Container(
height: height,
width: width,
margin: EdgeInsets.symmetric(
horizontal: 10, vertical: 10),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(
20),
boxShadow: [
BoxShadow(
color: Colors.blueGrey
.shade100,
blurRadius: 5,
spreadRadius: 3)
]),
child: Align(
alignment: Alignment.center,
child: Column(children: [
Padding(
padding:
EdgeInsets.only(
left: 15, top: 8),
child: Text(
&quot;Dr. &quot; + data[&#39;doctorName&#39;],
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight
.bold,
color: Colors
.blueAccent),
)),
Padding(
padding: EdgeInsets.only(
top: 5),
child: Text(
data[&#39;doctorType&#39;],
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 15,
color: Colors.grey),
)),
const Divider(
height: 22,
thickness: 0.4,
color: Colors.grey,
),
Row(
children: [
Icon(Icons
.access_time_outlined),
Expanded(
flex: 1,
child: Text(
data[&#39;bookingStart&#39;],
style: TextStyle(
fontSize: 16,
color: Colors
.black87
.withOpacity(
0.5)),
)),
Icon(Icons
.location_on_outlined),
Expanded(
flex: 1,
child: TextButton(
onPressed: () {
opentApptMap();
},
child: Text(
data[&#39;hospitalName&#39;],
textAlign: TextAlign
.center,
style: TextStyle(
decoration: TextDecoration
.underline),
)),
)
],
),
Padding(
padding:
const EdgeInsets.only(
top: 5.0),
child: Row(
children: &lt;Widget&gt;[
Expanded(
child: SizedBox(
// width: 80,
height: 30,
child: ElevatedButton(
child: const Text(
&quot;Cancel&quot;),
onPressed: () {
Navigator.of(
context).push(
MaterialPageRoute(
builder: (
context) =&gt;
CancelApptBox(i)));
},
style:
ElevatedButton
.styleFrom(
shape:
StadiumBorder(),
textStyle: TextStyle(
fontSize: 15,
)),
),
),
),
Padding(
padding:
EdgeInsets.only(
right: 8)),
Expanded(
child: SizedBox(
// width: 80,
height: 30,
child: ElevatedButton(
child:
const Text(
&quot;Reschedule&quot;),
onPressed: () {},
style:
ElevatedButton
.styleFrom(
shape:
StadiumBorder(),
textStyle: TextStyle(
fontSize: 15,
)),
),
),
)
],
))
])),
);
}else{
print(&quot;no appts&quot;);
}
});
} else {
return Text(&quot;else&quot;);
}
})

答案3

得分: 0

如果您想从集合中删除特定数值,您必须提供要删除的文档标识符。在上面的代码片段中,您正在提供所有文档标识符来执行删除操作,这就是为什么所有文档都被从集合中删除的原因。

如果您想删除特定项,请按照以下步骤操作:

  1. 获取整个集合。
  2. 从集合中找到要删除的标识符。
  3. 将该标识符传递给删除方法。

注意:如果您已经有一个需要删除的标识符,请忽略“第一”点。

英文:

If you want to delete a specific value from a collection, you must provide the document id that you want to delete.In above snippet you are providing all document id to delete method.That's why all docs are being removed from collection.

If you want to delete a specific item, follow the steps below.
1)Get whole collection.
2)Find the id from collection that you want to delete.
3)Pass that id to delete method.

Note:If you already have an ID that needs to be deleted, ignore the "First" point.

huangapple
  • 本文由 发表于 2023年3月7日 18:57:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/75661088.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定