How can I append a new Map type in firestore?
void addUser() async {
final us = _firestore.collection("users").doc(_search.text);
us.update({
"requests": (
{_auth.currentUser?.email: rep}
),
});
}
Am using this method but the requests field in my firestore overwrites the previous one I want it to be appended. Any idea?
The update() method will always overwrite your previous field with the new one, so achieving this with one operation using the update() is not possible, however, you can always get the current field from the document, then update its value, then save it again in the document like this:
void addUser() async {
final us = _firestore.collection("users").doc(_search.text);
final currentDoc = await us.get(); // we get the document snapshot
final docDataWhichWeWillChange = currentDoc.data() as Map<String, dynamic>; // we get the data of that document
docDataWhichWeWillChange{"requests"]![_auth.currentUser?.email] = rep; // we append the new value with it's key
await us.update({
"requests": docDataWhichWeWillChange["requests"],
}); // then we update it again
}
But you should use this after being aware that this method will make two operations in your database, a get() and update().
If you want to record multiple values, an array is an appropriate type. So, you could use the .arrayUnion method to record multiple entries.
final washingtonRef = db.collection("cities").doc("DC");
// Atomically add a new region to the "regions" array field.
washingtonRef.update({
"regions": FieldValue.arrayUnion(["greater_virginia"]),
});
Related
If you see the screenshot of my database, the data is stored in a nested way (cartProduct is a key which has a value of an entire Json file with keys: "id", "price" etc.). In my code, I create a map of each record in the "Orders" table in order to retrieve key values of any key that I specify. This is done by specifying the key name in the databaseMapper variable.
I am trying to read the value of each "id" and store it in a list called "testerList". I am able to store each orderNum, totalAmount or any of those key values that I specify in the databaseMapper. However, if I specify ["id"] it does not work.
I did some research and saw that the only way to reference nested items in a map is by using the logic: databaseMapper["cartProduct"]["id"] like I did below, but I keep getting an error (see last screenshot).
Any help would be appreciated!
Future _readItemIDsTest() async {
//Stores each record in the table as a map
var snapshot = await _dbRef.child("Orders").get();
snapshot.children.forEach((childSnapshot) {
var databaseMapper = childSnapshot.value as Map;
testerList.addAll([databaseMapper["cartProduct"]["id"]]);
});
print(testerList);
}
Nvm, I figured it out. The code below solved my issue.
Future _readItemIDsTest() async {
//Stores each record in the table as a map
//Adds the itemName value of each item from the map
var snapshot = await _dbRef.child("Orders").get();
snapshot.children.forEach((childSnapshot) {
databaseMapper = childSnapshot.value as Map;
var cartProductList = databaseMapper["cartProduct"];
(cartProductList as List).forEach((cartProductElement) {
testerList.addAll([cartProductElement["id"]]);
});
});
print(testerList);
}
I am trying to update records in my Back4App database. The problem is that ..objectId = currentUser.objectId takes only the userid and there can be multiple records for the same id. Thus, I am unable to update a single record of that userid. I am trying to filter by te unique id of records "concatid" but nothing gets updated.
Future<void> updateTodo(String description, String dogName) async {
ParseUser? currentUser = await ParseUser.currentUser() as ParseUser?;
var concatid = currentUser!.objectId! + dogName;
await Future.delayed(Duration(seconds: 1), () {});
final todo = ParseObject('Todo')
..objectId = currentUser.objectId
..set('concatId', concatid)
..set('DogDescription', description);
await todo.save();
}
Here's the documentation about update methods, but it only takes into account a general approach where you can only set new data matching by objectId and assuming this is unique (which is not my case).
I am building an Appointment Booking application want to retrieve all my documents from firestore at once on a button click. I used this:
Future<void> userAppointmentHistory() async {
String collectionName =
FirebaseAuth.instance.currentUser?.displayName as String;
String doc_id = "YyWqd9VlB1IdmYoIIFTq";
await FirebaseFirestore.instance
.collection(collectionName)
.doc(doc_id)
.snapshots()
.listen(
(event) {
print(
event.get("selectedDate"),
);
},
);
}
From the above code, I am getting only the specified document id details. So please help me modify the above code so that I get all the document details as I want to display these details on cards as my booked appointment history.
Here you are passing the doc id String doc_id = "YyWqd9VlB1IdmYoIIFTq";
You don't want to pass that if you want the full documents.
just pass the collection reference.
Follow the below code
fetchData() {
CollectionReference collectionReference =
FirebaseFirestore.instance.collection(collectionName);
collectionReference.snapshots().listen((snapshot) {
setState(() {
document = snapshot.docs;
});
print(document.toString);
});
}
Rudransh Singh Mahra,
It's as easy as putting text widget in our application.
Solution
You did it in right way but by mistake you have passed a specific id of documents in doc() as doc('YyWqd9VlB1IdmYoIIFTq'). you just need to remove that id from there and you may get your desired output.
What actually happens :
In your query you pass specific docId. So that it will returns that specified id document from your collection. To get all the documents from that collection you just need to do as follows,
Future<void> userAppointmentHistory() async {
String collectionName =
FirebaseAuth.instance.currentUser?.displayName as String;
// String doc_id = "YyWqd9VlB1IdmYoIIFTq";
await FirebaseFirestore.instance.collection(collectionName).doc().get()
}
And you will get your desired output if collectionName is valid and exist in firestorm database.
I'm creating a simple job board site.
You have a JobSeeker, a JobListing and a JobApplication
Both the JobSeeker and the JobListing should have a collection of JobApplications.
When a JobSeeker applies for a job, I want to create a JobApplication document, and add it to both the JobSeeker's collection, and the JobListing's collection.
But that should be a reference to a single document. (ie. if you update it in one place, it should update in the other).
How do I achieve this?
I see according to this answer:
Cloud Firestore multiples document with the same reference
I can add a Reference as a datatype in Firestore - but I'm not exactly sure which method to use to add it.
ie. the collection.add method accepts DocumentData, but I can't see how to set that as a reference?
Can you tell me what syntax to use to:
Create the JobApplication document
Add the document reference to a collection.
Retrieve the document reference from either collection.
Here's the way I ended up solving this:
To set the data:
const docData = {
listingId: "someExistingId",
jobSeekerId: "anotherExistingId",
otherData: "whatever other data goes here",
}
const docRef = await db.collection("job-application-collection")
.add(docData);
await db.collection(`job-seeker-collection/${docData.jobSeekerId}/applications`)
.add({ref:docRef});
await db.collection(`job-listing-collection/${docData.listingId}/applications`)
.add({ref:docRef});
That as, what we do is we create one 'real' document, that goes into the job-application-collection and in the JobSeeker and JobListing collections we add a 'pointer document' that just contains a single field ref, containing the document reference.
To retrieve it (in this example, retrieve all of the applications for a given JobSeeker):
const jobSeekerId = "someJobSeekerId";
const colRef = await db.collection(`job-seeker-collection/$jobSeekerId}/applications`);
const colSnapshot = await colRef.get();
/**
* The docs on the collection are actually just documents containing a reference to the actual JobApplication document.
*/
const docsProms = colSnapshot.docs.map((async (colDocData) => {
const snapshot = await colDocData.data().ref.get();
return {
...snapshot.data(),
id: snapshot.id,
}
}));
const data = await Promise.all(docsProms);
return data;
Pretty straight forward, we get the collection on the JobSeeker document, and then on each of those documents, there is a ref field, which we can use the .get() method to return a document snapshot.
I'm currently working on an app where I have to retrieve data from Google's Firestore.
My data structure looks like this:
users
- name#xxx.com
- more data
Is there a way for me to change the name#xxx.com to just name?
I can't see a method to change the name of a document.
I think the best way to do this is to get the data from 'name#xxx.com' and upload it to a new document called 'name' and then delete the old one.
Just as an example:
const firestore = firebase.firestore();
// get the data from 'name#xxx.com'
firestore.collection("users").doc("name#xxx.com").get().then(function (doc) {
if (doc && doc.exists) {
var data = doc.data();
// saves the data to 'name'
firestore.collection("users").doc("name").set(data).then({
// deletes the old document
firestore.collection("users").doc("name#xxx.com").delete();
});
}
});
There might be a case when u realize that you should have used autogenerated IDs for all your firebase documents in a collection and now you want to change the document IDs in your Collection ("collection_name") and also want to store their previous IDs as a new field ("prevID") in the new document then here's what you can do:-
FirebaseFirestore firebaseDb;
ArrayList<Map<String,Object>> data = new ArrayList<>();
firebaseDB.collection("collection_name").get.addOnSuccessListener(
queryDocumentSnapshots -> {
for (DocumentSnapshot d : queryDocumentSnapshots) {
Map<String,Object> map = d.getData();
map.put("prevID", d.getId());
data.add(map);
}
for(Map<String, Object> d : data){
Task<DocumentReference> dd = firebaseDb.collection("collection_name").add(d);
dd.addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
#Override
public void onSuccess(DocumentReference documentReference) {
firebaseDb.collection("collection_name").document((String) d.get("prevID")).delete();
}
});
}
});