Firebase Cloud Firestore Queries using Javascript(NodeJs)
How To Save, Update And Delete Data In Firebase Cloud Firestore
Connection code with Firebase:
You will find this below code from your firebase project. Copy that code in your project folder to establish connection with firebase.
var firebase = require(“firebase/app”);// dependencies of firebase authenticationrequire(“firebase/auth”);
// dependencies of firebase firestorerequire(“firebase/firestore”);require(“firebase/analytics”);// Your web app’s Firebase configurationvar firebaseConfig = {apiKey: “AIzaSyDsQW6XOLvacHCoCE4_aylbPnb0vqacyTI”,authDomain: “fir-app-f3d37.firebaseapp.com”,databaseURL: “https://fir-app-f3d37.firebaseio.com",projectId: “fir-app-f3d37”,storageBucket: “fir-app-f3d37.appspot.com”,messagingSenderId: “369290148095”,appId: “1:369290148095:web:dc3f12db73c3a98f3a74ca”};// Initialize Firebasefirebase.initializeApp(firebaseConfig);module.exports=firebase;
First off, we need to create a constant that holds the different Firestore functions needed for the different operations.
const database = firebase.firestore();
Save Data
const usersCollection = database.collection('users');function storeUserData(firstName,lastName,age) {
const ID = usersCollection.doc('user01').set({
first_name: firstName,
last_name: lastName,
age: age
})
.then(()=>{
console.log('Data has been saved successfully !')})
.catch(error => {
console.error(error)
});}
The then
and catch
blocks are optional.
Add A Field To A Document
Let’s say we want to add data to a document. If we use set
, all the data in that document will be overwritten. Therefore to prevent the old data loss, we need to add another parameter to the set
method.
The second parameter of set
is an object that has the merge
property. merge
needs to be set to true
. Thus if we try to add another field to the document, it will overwrite only the field if it exists. If the field doesn’t already exist it will be added.
const usersCollection = database.collection('users');function storeUserData(firstName,lastName,age) {
const ID = usersCollection.doc('user01').set({
first_name: firstName,
last_name: lastName,
age: age
},{merge:true})
.then(()=>{
console.log('Data has been saved successfully !')})
.catch(error => {
console.error(error)
});}
Auto-Generated IDs
Up until now we’ve been hard coding the documents identifiers. However, if we want them to be automatically generated we can use the add
method instead of set
.
const usersCollection = database.collection('users');function addUser(firstName,lastName,age) {
const ID = usersCollection.add({
first_name: firstName,
last_name: lastName,
age: age
});
});
Furthermore, we can store an identifier in a constant using the doc
method without a parameter. Then use it later calling the set
method on it.
const usersCollection = database.collection('users');function addUser(firstName,lastName,age) {
const ID = usersCollection.doc();
ID.set({
first_name: firstName.value,
last_name: lastName.value,
age: Number(age.value)
});
});
Update Data
To update data we should simply specify the document’s reference and use the update
method. update
takes an object that holds the new data as a parameter.
const usersCollection = database.collection('users');updateBtn.addEventListener('click', e => {
e.preventDefault();
usersCollection.doc(userId.value).update({
first_name: firstName.value,
last_name: lastName.value,
age: Number(age.value)
});
});
Update Objects
Updating an object is a bit tricky. If you thought that we could just specify the name of the field and set the new property. Well, that’s because all of the data in the object will be overwritten.
const usersCollection = database.collection('users');updateBtn.addEventListener('click', e => {
e.preventDefault();
usersCollection.doc(userId.value).update({
favorite: {
food: 'Pizza'
}
});
});
That being said, the right way of updating an object is to specify the name of the object, followed by a dot, then the name of the property.
const usersCollection = database.collection('users');updateBtn.addEventListener('click', e => {
e.preventDefault();
usersCollection.doc(userId.value).update({
'favorite.food': 'Pizza'
});
});
Update Arrays
Updating arrays is also quite different. As there are certain prebuilt functions to use in order to update this type of data.
So to add data to an array we should use the arrayUnion
function.
//adding map data to arraysconst contactData = firebase.firestore().collection('ContactUs').doc(uid);contactData.set({UserContactData:
firebase.firestore.FieldValue.arrayUnion(contactDataMap)},{merge:true})//adding value to arraysconst usersCollection = database.collection('users');
usersCollection.doc(userId.value).update({
favorite_color:
firebase.firestore.FieldValue.arrayUnion('Yellow') });
//nesting arraysconst usersCollection = database.collection('users');values=['yesllow','green','red'];usersCollection.doc(userId.value).update({
favorite_colors:
firebase.firestore.FieldValue.arrayUnion.apply(null, values)FieldValue.arrayUnion.apply(null, values)});
To delete data from an array we should use the arrayRemove
function.
const usersCollection = database.collection('users');updateBtn.addEventListener('click', e => {
e.preventDefault();
usersCollection.doc(userId.value).update({
favorite_color: firebase.firestore.FieldValue.arrayRemove('Green')
});
});
Useful Functions
Firestore provides a handful of useful functions. serverTimestamp
is one of them. This function returns the timestamp of the document’s update.
const usersCollection = database.collection('users');updateBtn.addEventListener('click', e => {
e.preventDefault();
usersCollection.doc(userId.value).update({
updated: firebase.firestore.FieldValue.serverTimestamp
});
});
increment
is also a very helpful function that you can use to increment and decrement numeric values.
const usersCollection = database.collection('users');updateBtn.addEventListener('click', e => {
e.preventDefault();
usersCollection.doc(userId.value).update({
age: firebase.firestore.FieldValue.increment(8)
//decrement
//age: firebase.firestore.FieldValue.increment(-8)
});
});
Delete Data
Delete A Field
Deleting a field from within a document is considered an update. Therefore we need to use the update
method, then call the delete
function on the field we wish to remove.
const usersCollection = database.collection('users');updateBtn.addEventListener('click', e => {
e.preventDefault();
usersCollection.doc(userId.value).update({
favorites: firebase.firestore.FieldValue.delete()
});
});
Delete A Document
Deleting a document is also pretty easy. This time we just need to specify the document’s location and then call the delete
method on it.
const usersCollection = database.collection('users');removeBtn.addEventListener('click', e => {
e.preventDefault();
usersCollection.doc(userId.value).delete();
});
How To Read Data In Firebase Cloud Firestore
The get Method
To read data from the database we need to use the get
method on the reference of a document.
const usersCollection = database.collection('users');readBtn.addEventListener('click', e => {
e.preventDefault();
usersCollection.doc(userId.value).get()
.then(user => {
if(user.exists)
console.log(user.data());
else
console.log('User does not exist !');
})
.catch(error => {
console.error(error);
});
});
The exists
property informs about the existence of the document. Because the nonexistence of a document doesn’t count as an error.
Now to get the data of all the documents within a collection. We need to use the get
method directly on the collection’s reference.
const usersCollection = database.collection('users');readBtn.addEventListener('click', e => {
e.preventDefault();
usersCollection.get().then(snapshot => {
snapshot.forEach(user => {
console.log(user.id, ' => ', user.data());
});
})
.catch(error => {
console.error(error);
});
});
user.id
returns the document’s identifier and user.data()
returns the data within it.
Querying The Database
To query the database based on a field’s value as a criterion. We need to use the where
method which is similar to the where
clause in SQL databases.
So let’s say we want to query the database based on the value of the last_name field. Then, in this case, we should use the where
method.
The first parameter should contain the field’s key. The second parameter is the querying operator. And finally, the third one is the value we want to query based on.
These are the 8 querying operators >
, >=
, ==
, <
, <=
, in
, array-contains
, array-constains-any
. Each is suitable for a certain need.
const usersCollection = database.collection('users');readBtn.addEventListener('click', e => {
e.preventDefault();
const query = usersCollection.where('last_name', '==', 'Yasmina');
query.get().then(snapshot => {
snapshot.forEach(user => {
console.log(user.id, ' => ', user.data());
});
})
.catch(error => {
console.error(error);
});
});
Furthermore, we can chain multiple queries. However the fields within the where
calls in the query must be the same.
const usersCollection = database.collection('users');readBtn.addEventListener('click', e => {
e.preventDefault();
const query = usersCollection.where('age', '>', 18).where('age', '<=', 32);
query.get().then(snapshot => {
snapshot.forEach(user => {
console.log(user.id, ' => ', user.data());
});
})
.catch(error => {
console.error(error);
});
});
As you might have noticed in this example. I used the age field as a criterion in both of the where methods.
Querying Based On Array Values
Arrays, on the other hand, have special operators. Therefore to get documents that have a certain value in a field which must be an array. We should use the array-contains
operator.
const usersCollection = database.collection('users');readBtn.addEventListener('click', e => {
e.preventDefault();
const query = usersCollection.where('favorite_languages', 'array-contains', 'Javascript');
query.get().then(snapshot => {
snapshot.forEach(user => {
console.log(user.id, ' => ', user.data());
});
})
.catch(error => {
console.error(error);
});
});
We can also get documents that have a value or more among other values that we specify in another array. That can be done through the array-contains-any method.
const usersCollection = database.collection('users');readBtn.addEventListener('click', e => {
e.preventDefault();
const languages = ['C', 'Java', 'Delphi', 'C++'];
const query = usersCollection.where('favorite_languages', 'array-contains-any', languages);
const query = usersCollection.where('age', '>=', 30).where('age', '<', 40);
query.get().then(snapshot => {
snapshot.forEach(user => {
console.log(user.id, ' => ', user.data());
});
})
.catch(error => {
console.error(error);
});
});
In this example, if a user has C, Java, Delphi or C++ in their favorite_languages field they should be selected.
Keep in mind that arrays that are set for the comparison can’t take any more than 10 values to search for.
Listeners In Firebase Cloud Firestore
Same as Firebase Realtime Database, we can attach listeners to the references in the database. So whenever an event occurs, a callback function gets triggered to execute whatever code you put inside of it. To so we need to use the onSnapshot
method. Consequently, we can get the new data after the event using the data
function.
usersCollection.doc('user01').onSnapshot(snapshot => {
console.log('Current data: ', snapshot.data());
}, error => {
console.log('Error !');
});
Furthermore, we can attach listeners to more than a single document using the where
method.
usersCollection.where('last_name', '==', 'Doe').onSnapshot(snapshot => {
snapshot.forEach(user => {
console.log('The user with the ID ', user.id, ' has been updated/added/deleted');
});
});
We can also get the type of the event that occurred on the reference, through the type
property for each document found by the where
method.
usersCollection.where('age', '==', 44).onSnapshot(snapshot => {
snapshot.docChanges().forEach(change => {
if(change.type === 'added')
console.log('Add operation has been done !');
if(change.type === 'changed')
console.log('change operation has been done !');
if(change.type === 'removed')
console.log('Delete operation has been done !');
}, error => {
console.log(error);
});
});
The docChanges
here is a function that returns an array, this array contains the list of changes that occurred on each the documents.