How to delete documents that contain a certain value in one of the fields. Firestore, Flutter - flutter

enter image description here
I have these documents, which contain data about each task I add to the list in my app.
child: StreamBuilder(
stream: _tasks.snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> streamSnapshot) {
if (streamSnapshot.hasData) {
return ListView.builder(
itemCount: streamSnapshot.data!.docs.length,
itemBuilder: (context, index) {
final DocumentSnapshot documentSnapshot =
streamSnapshot.data!.docs[index];
return GestureDetector(
onLongPress: () => _update(documentSnapshot),
child: ListTile(
)
);
},
);
}
return const Center(
child: CircularProgressIndicator(),
);
},
),
I am using a stream builder to build the list. Each of the tasks have a checkmark and when i click it, It updates the value in firestore inside the IsDone field accordingly. I want to click a button outside the stream builder to delete the checked tasks. How do I loop through all the documents and find all the documents that contain the value true and delete them?
I tried this but im doing doing something wrong and it isnt changing anything:
void _delete() {
var docs = _tasks.doc().snapshots();
docs.forEach((doc){
if(doc.data()==true){
_tasks.doc(doc.id).delete();
}
});
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text('You have successfully deleted a product')));
}

var datas = await FirebaseCalls.firebaseFirestore
.collection("collection_id")
.where("status", isEqualTo: true)
.get();
datas.docs.forEach((element) {
FirebaseFirestore.instance
.collection("collection_id")
.doc(element.id)
.delete();
});
or you can do like this as well.
var datas =
await FirebaseCalls.firebaseFirestore.collection("collection_id").get();
datas.docs
.where((element) => element["status"] == true)
.toList()
.forEach((el) {
FirebaseFirestore.instance
.collection("collection_id")
.doc(el.id)
.delete();
});

You can delete by doing this below:
find the particular document as per your query and get its document and collection ID.
FirebaseFirestore.instance
.collection("collection_id")
.doc("doc_id")
.delete();

Related

firestore doesnt show documents even though they are available

I have following code to add data to firebasefirestore
Future<void> sendMessage({
required String msg,
required String id,
}) async {
var docId = getDocId(id); // returns sth like "AbcDe-FghiJ"
DocumentReference documentReferencer = chat.doc(docId).collection('chatMsg').doc();
Map<String, dynamic> data = <String, dynamic>{
"message": msg,
"sentBy": ownId,
"sentAt": DateFormat('yyyy-MM-dd – kk:mm:ss').format(DateTime.now())
};
await documentReferencer.set(data);
}
I used following code to get the data
StreamBuilder<QuerySnapshot>(
stream: firebaseInstance.collection('Messages').snapshots(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasError || !snapshot.hasData) {
return const Center(
child: CircularProgressIndicator()
);
} else {
var data = snapshot.data.docs;
return listBuilder(data);
}
}
)
listBuilder(listData) {
return ListView.builder(
shrinkWrap: true,
itemCount: listData.length,
itemBuilder: (BuildContext context, int index) {
return Text(listData[index].id);
}
)
}
However, data show 0 items even though there is a document present.
My question is how can I get the list of documents from Messages?
I was having the same exact problem with subcollections on Firestore and even asked a question here to get some help over it. Though, it seems like the snapshots won't show the documents having a subcollection in them as there is no field inside any of them. So what I did to counter this was to just add anything (just a random variable) and then it was able to find the documents.
This is my current layout:
I've just added another line of code to just add this whenever I'm inserting a new subcollection.
collection
.set({
'dummy': 'data'
})
.then((_) => print('Added'))
.catchError((error) => print('Add failed: $error'));

How can I get data from various nodes in a Realtime-database in Flutter?

I'm trying to display data from a real-time database in my widget, such as a picture, a name, or a message, but I'm not sure how to achieve it from several nodes. Thank you in advance for your assistance.
For add data :
List lists = [];
stream to get data :
final dbRef = FirebaseDatabase.instance
.ref()
.child("chatList")
.child("D1NilPUI6PY0jSA1tk0wRzi6FsO2");
Widget to show data :
_widget() {
return StreamBuilder(
stream: dbRef.onValue,
builder: (BuildContext context, AsyncSnapshot snap) {
if (snap.hasData &&
!snap.hasError &&
snap.data!.snapshot.value != null) {
Map data = snap.data.snapshot.value;
List item = [];
data.forEach((index, data) => item.add({"chatList": index, ...data}));
print("DATA : $item");
if (snap.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator();
} else {
return ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: item.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(item[index]['content'].toString()),
);
},
);
}
} else {
return const Center(child: Text("No data"));
}
},
);
}
Table structure Images :
Image 1 :
Image 2 :
This code:
final dbRef = FirebaseDatabase.instance
.ref()
.child("chatList")
.child("D1NilPUI6PY0jSA1tk0wRzi6FsO2");
This refers to a node /chatList/D1NilPUI6PY0jSA1tk0wRzi6FsO2 in your database. Since the screenshot doesn't show any data under that exact path, you will get a snapshot without any value from reading it.
If you want to read all nodes under /chatList, you can use that path in the query, and then loop over all the children of the snapshot.
final dbRef = FirebaseDatabase.instance
.ref()
.child("chatList");
dbRef.onValue.listen((event) => {
event.snapshot.children.forEach((child) {
print(child.key);
})
})
Since you have two levels with dynamic keys under chatList, you'll have to use two nested loops to get to the named properties:
final dbRef = FirebaseDatabase.instance
.ref()
.child("chatList");
dbRef.onValue.listen((event) => {
event.snapshot.children.forEach((child) {
print(child.key);
child.children.forEach((child2) {
print(child2.key);
print(child2.child("lastMessage/content").value);
})
})
})

Flutter SqlBrite not rebuilding streambuilder list

I am trying to build a chat storage system with firebase, sqlite and sqlBrite.
The aim of this is to stream the newmessages without having to rebuild the page. The stream from sqlBrite is only rebuilding on setstate eg.when the keyboard is drawn back.
How can i get the stream to automatically update on save.
The db document
///INSERT INTO DB
Future<int> insertNewMessage(String id, int result, BriteDatabase briteDb,
Map<String, dynamic> row) async {
messageList.add(id);
await ifexists(id, messageId, briteDb)
? print('message already In')
: result = await briteDb.insert(messageTable, row);
return result;
}
////STREAM MESSAGES
Stream<List<Map<String, dynamic>>> getMessageMapListbyId(
{String sendId, String receiveId, database}) async* {
try {
BriteDatabase briteDb = await database;
yield* briteDb.createQuery(messageTable,
distinct: false,
where:
' $senderId=? $receiverId = ? ',
whereArgs: [
sendId,
receiverId,
])});
provider document
///ADD MESSAGES
addMessageTodb(message) async {
await ldbH
.msg_insertMessage(
message.id, modelFuncs.messageMaping(message, msgFuncs))
.then((value) async {
await getMessageYieldBase(message.senderId, message.receiverId);
});}
///STREAM NEW DATA
getMessageYieldBase(senderId, receiverId) async* {
yield* ldbH.msg_getAllMessagesbyId(senderId, receiverId);}
The ui side
StreamBuilder(
stream: messageStream.getMessageYieldBase(
widget._currentUserId, widget.receiver.uid),
builder: (context, AsyncSnapshot<dynamic> snapshot) {
var d = snapshot.data;
var newList = snapshot.hasData ? d.reversed.toList() : [];
return
ListView.builder(
reverse: true,
padding: EdgeInsets.all(10),
controller: widget._listScrollController,
itemCount: newList.length,
itemBuilder: (BuildContext context, int index) {
return DisplayMessage(
currentUserId: widget._currentUserId,
receiver: widget.receiver,
message: newList[index],
);
});
})
So the new texts keep coming only when the page rebuilds in some sort of way.
Any help rendered is appreciated.
If you are facing this problem use the moor library sqlbrite won't work but this is a link to help....
https://resocoder.com/2019/06/26/moor-room-for-flutter-tables-queries-fluent-sqlite-database/
Matt Rešetár explains in detail so it will be easy to implement...

How to order Firestore documents in list form based on int values in flutter

I currently have a list of documents that each contain an int value called plastics. Currently, the list only displays the documents in order by when it was added to the collection, but I want to be able to order the documents based on the int value within each one. I've looked around on the web and I've only found tutorials mostly on ordering timestamps. Is there any documentation or sources on this matter? Here is the code situation I'm working with:
Firstly, in my app users can join groups, and when they do so they bring along their name and int data which is then stored in documents for each user.
Future<String> joinGroup(String groupId, String userUid, String displayName,
String plastics) async {
String retVal = 'error';
List<String> members = List();
try {
members.add(displayName);
await _firestore.collection('Groups').doc(groupId).update({
'members': FieldValue.arrayUnion(members),
});
final uid = FirebaseAuth.instance.currentUser.uid;
await _firestore.collection('UserNames').doc(uid).update({
'groupId': groupId,
});
//Below me is the code for doing so
await _firestore
.collection("Groups")
.doc(groupId)
.collection("Members")
.doc(userUid)
.set({'displayName': displayName, 'plastics': plastics});
retVal = 'success';
} catch (e) {}
return retVal;
}
I then take that code access the documents and put them in a list.
#override
Widget build(BuildContext context) {
final CollectionReference users = firestore.collection('UserNames');
final String uid = auth.currentUser.uid;
return FutureBuilder(
future: users.doc(uid).get(),
builder: (context, snapshot) {
if (snapshot.hasData) {
final result = snapshot.data;
final groupId = result.data()['groupId'];
return FutureBuilder<QuerySnapshot>(
// <2> Pass `Future<QuerySnapshot>` to future
future: FirebaseFirestore.instance
.collection('Groups')
.doc(groupId)
.collection('Members')
.get(),
builder: (context, snapshot) {
if (snapshot.hasData) {
// <3> Retrieve `List<DocumentSnapshot>` from snapshot
final List<DocumentSnapshot> documents = snapshot.data.docs;
return ListView(
children: documents
.map((doc) => Card(
child: ListTile(
title: Text(doc['displayName']),
subtitle: Text(doc['plastics'].toString()),
),
))
.toList());
} else if (snapshot.hasError) {
return Text('Its Error!');
}
});
}
});
}
Is there a specific function needed so that the documents in the Member collection are listed based on the numerical value of the plastics?
You can use orderBy to sort your results.
FirebaseFirestore.instance
.collection('Groups')
.doc(groupId)
.collection('Members')
.orderBy('plastics', descending: true)
.get()

Flutter How to apply search filter in a querysnapshot used in Listview builder

This is my firebase data request code
and this is my future builder based on the qn.docs
How to search within the snapshot and ListView.builder to use the filtered set.
previously I was using a Local List and used to search as on Itemchanged
thanks in advance for your guidance.
I am new to flutter. so please explain with an example
Future <QuerySnapshot> getSpeakernames() async {
QuerySnapshot qn = await
FirebaseFirestore.instance.collection('speakernames').orderBy('speakername').get();
return qn;
}
Center(
child: Container(
child: ListView.builder(
itemCount: snapshot.data.docs.length,
itemBuilder: (BuildContext context, int index) {
DocumentSnapshot data = snapshot.data.docs[index];
return ListTile(title: Text(data.get("speakername")),
subtitle: Text(data.get("speakerdegree")), )
onItemChanged(String value) {
setState(() {
data.get("speakername").
newspeakernames = speakernames
.where((string) =>
string.toLowerCase().contains(value.toLowerCase()))
.toList();
});
}
you can use ".Where" property of Firestore
like below
Future <QuerySnapshot> getSpeakernames() async {
QuerySnapshot qn = await FirebaseFirestore.instance.collection('speakernames')
.where('speakername' , isEqualTo : SubramanianV).orderBy('speakername').get();
return qn;
}
You can use isGreaterThanOrEqualTo.
Example:
class doctorName {
getDoctorByName(String doctorName, String last) async {
return await Firestore.instance
.collection("Doctor")
.where("name", isGreaterThanOrEqualTo: doctorName)
.where("name", isLessThan: last)
//.where("name", isEqualTo: doctorName)
.getDocuments();
}
}