How to pull data from inside arrays in firestore - firebase

So I have a main field EmailFrom and inside it has arrays with some info of their own.
I am trying to pull this data from firestore but I am not sure how to go about it.
Here is how I am pulling data currently
var user = firebase.auth().currentUser.uid;
let cityRef = db.collection("Users").doc(user);
let getDoc = cityRef
.get()
.then((doc) => {
if (!doc.exists) {
console.log("No such document!");
} else {
console.log("Document data:", doc.data());
let z = 0;
for (z = 0; z < 5; z++) {
let data = doc.data();
let emailBody = data.EmailBody;
let emailsubject = data.EmailSubject;
let emailSubject = emailsubject[z];
let olddate = data.EmailDate;
let oldDate = olddate[z];
let emailDateYear = new Date(oldDate).getFullYear();
let emailDateMonth = new Date(oldDate).getMonth();
let emailDateDay = new Date(oldDate).getDate();
let emailfrom = data.EmailFrom;
let emailFrom = emailfrom[z];
console.log(olddate);
so basically I am trying to use the data.EmailFrom[arrayNumber] method to pull the data in my current setup but because this data is like further inside the array I am not sure how to access it. Tried searching online and cannot find much to help me on this one. Any help would be appreciated =]

The following should do the trick:
const data = doc.data();
const address = data.EmailFrom[0].value[0].address;

Related

firestore : why retrieved data is not getting into an variable in cloud functions

I retrieved the data from firestore. when that retrieved data is storing into a variable I am getting [object object].I didn't understand why it happens?
My code is
var dbref = db1.collection('deyaPayUsers').doc(sendauthid).collection('Split').doc(sendauthid).collection('SentInvitations').doc(senderautoid);
var fulldoc = dbref.get()
.then(doc => {
if(!doc.exists){
console.log('No such document');
}else{
console.log('Document data :',doc.data());
d1 = doc.data();// here I am not getting the data
console.log("d1 is"+d1);
}
});
I dint know what you what you actually want to achieve, because you have shared incomplete code. However I hope code below will help you.
const db = firebase.firestore()
let self = this;
db.collection("User")
.get()
.then(function (querySnapshot) {
if (querySnapshot.size > 0) {
querySnapshot.forEach((result) => {
let data = result.data();
data.id = result.id;
console.log(data)
})
} else {
console.log("no data found")
}
}
);

I wanted to convert firebase timestamp to UTC timeview in react native

i have been searching for solution for 2 days now
here is my code
saveData = () =>{
let servertime = Firebase.database.ServerValue.TIMESTAMP;
this.itemsRef.push({name:this.state.text,date:servertime});
var s = new Date(parseInt(servertime)).toUTCString();
alert(s);
}
but alert return me with invalid value
i try to put an unix interger directly like this
saveData = () =>{
let servertime = Firebase.database.ServerValue.TIMESTAMP;
this.itemsRef.push({name:this.state.text,date:servertime});
var s = new Date(1509004701954).toUTCString();
alert(s);
}
and it work well
why cant i get the same result?
Firebase.database.ServerValue.TIMESTAMP is a constant that represents the object { ".sv": "timestamp" }. Firebase uses it to automatically put in the current timestamp.
You need to push the data, then grab the snapshot and read the 'date' back:
saveData = () => {
this.itemsRef.push(
{
name:this.state.text,
date:Firebase.database.ServerValue.TIMESTAMP
}).then((snapshot) => {
var s = new Date(parseInt(snapshot.val().date)).toUTCString();
alert(s);
}
}

Is It Possible To Get The ID Before It Was Added?

I know that in Realtime Database I could get the push ID before it was added like this:
DatabaseReference databaseReference= FirebaseDatabase.getInstance().getReference();
String challengeId=databaseReference.push().getKey();
and then I could add it using this ID.
Can I also get it in the Cloud Firestore?
This is covered in the documentation. See the last paragraph of the add a document section.
DocumentReference ref = db.collection("my_collection").doc();
String myId = ref.id;
const db = firebase.firestore();
const ref = db.collection('your_collection_name').doc();
const id = ref.id;
You can do this in following manner (code is for AngularFire2 v5, which is similar to any other version of firebase SDK say web, node etc.)
const pushkey = this.afs.createId();
const project = {' pushKey': pushkey, ...data };
this.projectsRef.doc(pushkey).set(project);
projectsRef is firestore collection reference.
data is an object with key, value you want to upload to firestore.
afs is angularfirestore module injected in constructor.
This will generate a new document at Collection called projectsRef, with its id as pushKey and that document will have pushKey property same as id of document.
Remember, set will also delete any existing data
Actually .add() and .doc().set() are the same operations. But with .add() the id is auto generated and with .doc().set() you can provide custom id.
Firebase 9
doc(collection(this.afs, 'posts')).id;
The simplest and updated (2022) method that is the right answer to the main question:
"Is It Possible To Get The ID Before It Was Added?"
v8:
// Generate "locally" a new document in a collection
const document = yourFirestoreDb.collection('collectionName').doc();
// Get the new document Id
const documentUuid = document.id;
// Sets the new document with its uuid as property
const response = await document.set({
uuid: documentUuid,
...
});
v9:
// Get the collection reference
const collectionRef = collection(yourFirestoreDb,'collectionName');
// Generate "locally" a new document for the given collection reference
const docRef = doc(collectionRef);
// Get the new document Id
const documentUuid = docRef.id;
// Sets the new document with its uuid as property
await setDoc(docRef, { uuid: documentUuid, ... })
IDK if this helps, but I was wanting to get the id for the document from the Firestore database - that is, data that had already been entered into the console.
I wanted an easy way to access that ID on the fly, so I simply added it to the document object like so:
const querySnapshot = await db.collection("catalog").get();
querySnapshot.forEach(category => {
const categoryData = category.data();
categoryData.id = category.id;
Now, I can access that id just like I would any other property.
IDK why the id isn't just part of .data() in the first place!
For node.js runtime
const documentRef = admin.firestore()
.collection("pets")
.doc()
await admin.firestore()
.collection("pets")
.doc(documentRef.id)
.set({ id: documentRef.id })
This will create a new document with random ID, then set the document content to
{ id: new_document_id }
Hope that explains well how this works
Unfortunately, this will not work:
let db = Firestore.firestore()
let documentID = db.collection(“myCollection”).addDocument(data: ["field": 0]).documentID
db.collection(“myOtherCollection”).document(documentID).setData(["field": 0])
It doesn't work because the second statement executes before documentID is finished getting the document's ID. So, you have to wait for documentID to finish loading before you set the next document:
let db = Firestore.firestore()
var documentRef: DocumentReference?
documentRef = db.collection(“myCollection”).addDocument(data: ["field": 0]) { error in
guard error == nil, let documentID = documentRef?.documentID else { return }
db.collection(“myOtherCollection”).document(documentID).setData(["field": 0])
}
It's not the prettiest, but it is the only way to do what you are asking. This code is in Swift 5.
docs for generated id
We can see in the docs for doc() method. They will generate new ID and just create new id base on it. Then set new data using set() method.
try
{
var generatedID = currentRef.doc();
var map = {'id': generatedID.id, 'name': 'New Data'};
currentRef.doc(generatedID.id).set(map);
}
catch(e)
{
print(e);
}
For the new Firebase 9 (January 2022). In my case I am developing a comments section:
const commentsReference = await collection(database, 'yourCollection');
await addDoc(commentsReference, {
...comment,
id: doc(commentsReference).id,
date: firebase.firestore.Timestamp.fromDate(new Date())
});
Wrapping the collection reference (commentsReference) with the doc() provides an identifier (id)
To get ID after save on Python:
doc_ref = db.collection('promotions').add(data)
return doc_ref[1].id
In dart you can use:
`var itemRef = Firestore.instance.collection("user")
var doc = itemRef.document().documentID; // this is the id
await itemRef.document(doc).setData(data).then((val){
print("document Id ----------------------: $doc");
});`
You can use a helper method to generate a Firestore-ish ID and than call collection("name").doc(myID).set(dataObj) instead of collection("name").add(dataObj). Firebase will automatically create the document if the ID does not exist.
Helper method:
/**
* generates a string, e.g. used as document ID
* #param {number} len length of random string, default with firebase is 20
* #return {string} a strich such as tyCiv5FpxRexG9JX4wjP
*/
function getDocumentId (len = 20): string {
const list = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ123456789";
let res = "";
for (let i = 0; i < len; i++) {
const rnd = Math.floor(Math.random() * list.length);
res = res + list.charAt(rnd);
}
return res;
}
Usage: const myId = getDocumentId().
This is possible now (v9 2022 update) by generating Id locally:
import { doc, collection, getFirestore } from 'firebase/firestore'
const collectionObject = collection(getFirestore(),"collection_name")
const docRef = doc(collectionObject)
console.log(docRef.id) // here you can get the document ID
Optional: After this you can create any document like this
setDoc(docRef, { ...docData })
Hope this helps someone. Cheers!
This works for me. I update the document while in the same transaction. I create the document and immediately update the document with the document Id.
let db = Firestore.firestore().collection(“cities”)
var ref: DocumentReference? = nil
ref = db.addDocument(data: [
“Name” : “Los Angeles”,
“State: : “CA”
]) { err in
if let err = err {
print("Error adding document: \(err)")
} else {
print("Document added with ID: \(ref!.documentID)")
db.document(ref!.documentID).updateData([
“myDocumentId” : "\(ref!.documentID)"
]) { err in
if let err = err {
print("Error updating document: \(err)")
} else {
print("Document successfully updated")
}
}
}
}
Would be nice to find a cleaner way to do it but until then this works for me.
In Node
var id = db.collection("collection name").doc().id;
If you don't know what will be the collection at the time you need the id:
This is the code used by Firestore for generating ids:
const generateId = (): string => {
// Alphanumeric characters
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let autoId = '';
for (let i = 0; i < 20; i++) {
autoId += chars.charAt(Math.floor(Math.random() * chars.length));
}
// assert(autoId.length === 20, "Invalid auto ID: " + autoId);
return autoId;
};
References:
Firestore: Are ids unique in the collection or globally?
https://github.com/firebase/firebase-js-sdk/blob/73a586c92afe3f39a844b2be86086fddb6877bb7/packages/firestore/src/util/misc.ts#L36

Geofire Query in Firebase Cloud Function

Sorry for my english, I have a doubt it is possible to make a query geofire in Firebase Cloud Func, with their respective key_enter and key_exited, in order to maintain a list of the geographic points near my position ?, extracted from a few hundred thousand. Taking into account that all this happens when the user updates its geolocation in a node firebase realtime database, and this list of hundreds of thousands is reduced to a few near the position of the user
The following is a trick I used to update with GeoFire
exports.testLocation = functions.database.ref('/tests/{test}').onWrite(event => {
let data = event.data.val();
console.log(data);
console.log(event.params.test);
if (data.location && data.location.coords) {
console.log('Update GeoFire');
geoBase = new geoBase(event.data.adminRef.parent.parent.child('/GeoFireTests'));
geoBase.addLocation(event.params.test, [data.location.coords.latitude, data.location.coords.longitude]);
}
});
GeoFire
let GeoFire = require('geofire');
module.exports = function(ref) {
this.geoFire = new GeoFire(ref);
this.addLocation = (key, location) => {
this.geoFire.set(key, location).then(() => {
console.log('Update succesfull');
}).catch(error => {
console.log(error);
});
}
}
This is how it would look like without the module
let functions = require('firebase-functions');
let GeoFire = require('geofire');
exports.testLocation = functions.database.ref('/items/{item}').onWrite(event => {
let data = event.data.val();
console.log(data);
console.log(event.params.item);
if (data.location && data.location.coords) {
console.log('Update GeoFire');
let ref = event.data.adminRef.parent.parent.child('/items_locations'));
let key = event.params.test;
let location = [data.location.coords.latitude, data.location.coords.longitude]);
let geoFire = new GeoFire(ref);
geoFire.set(key, location).then(() => {
console.log('Update succesfull');
}).catch(error => {
console.log(error);
});
}
}

How to join data from multiple locations in your Firebase DB?

I have an index of notification ids associated with a user X. When I want to display these notifications I need to fetch them from the user X's notifications index which just contains the
a) id of the notification (nid)
b) status: "read/unread"
But I also need to go to
a) /notifcations/nid to get my notification data: text and fromUser
b) /users/fromUser to get the user data for that user
My question is about structure.
Did i structure my data properly and if so, how can I fetch all this information inside the Notification and when ready, present it to angular for displaying on the screen.
Here is my take on that below. Any critique (code/structure/anything) is welcome. Thanks.
P.S.
Also if I am replacing POJOs in firebaseArray with instances of Notification, how would that affect my DB when I say edit the notification and save it back to Firebase. How does AngularFire know what to save back?
/* Notifications */
.factory('Notifications', function(firebaseUrl, NotificationsFactory){
var ref = new Firebase(firebaseUrl);
return {
getNotificationsForUser : function(uid){
var userNotifRef = ref.child('users').child(uid).child('notifications');
return new NotificationsFactory(userNotifRef);
}
}
})
.factory('NotificationsFactory', function($firebaseArray, Notification) {
return $firebaseArray.extend({
$$added : function(snapshot, prevChild){ //called anytime a 'child_added' event occurs
return new Notification(snapshot);
}
})
})
.factory('Notification', function(firebaseUrl, $q, Users) {
var notifRef = (new Firebase(firebaseUrl)).child('notifications');
var usersRef = (new Firebase(firebaseUrl)).child('users');
var mainDeferred = $q.defer();
var notifDeferred = $q.defer();
var userDeferred = $q.defer();
var Notification = function(snapshot){
this.$id = snapshot.key();
this.status = snapshot.val().status;
this.message = null;
this.from = null;
this.to = null;
notifRef.child(this.$id).once('value', function(snap){ //change to on if expect notification to keep updating
var data = snap.val();
this.message = data.message;
this.from = data.from; //user id
this.to = data.to; //user id
notifDeferred.resolve();
});
notifDeferred.promise.then(function(){
this.from = Users.getUser(this.from);
this.to = Users.getUser(this.to);
this.from.$loaded().then(function(){
this.to.$loaded().then(function(){
mainDeferred.resolve();
})
})
})
};
Notification.prototype.ready = function(){
return mainDeferred.promise;
}
return Notification;
})

Resources