Skip to content

Firestore – Code Template

CRUD

export const productsRef = db.collection("products");

Get

Once (No reactive)

async created() {
    const snap = await productsRef.get();
    snap.docs.forEach(doc => {
      const product = {
        id: doc.id,
        ...doc.data()
      }

      this.products.push(product);
    })
  }
}

Reactive (without Vuefire)

setup() {    
    const products = reactive([]);

    const getSyncFirestore = (collection, data) => {
      const unsubscribe = collection.onSnapshot(
        (ref) => {
          ref.docChanges().forEach((change) => {
            const { newIndex, oldIndex, doc, type } = change;
            if (type === "added") {
              data.splice(newIndex, 0, { id: doc.id, ...doc.data() }); // add
            } else if (type === "modified") {
              data.splice(oldIndex, 1); // remove old
              data.splice(newIndex, 0, { id: doc.id, ...doc.data() }); // add new
            } else if (type === "removed") {
              data.splice(oldIndex, 1); // remove
            }
          });
        },
        function (err) {
          console.log(err);
        }
      );
    };
    getSyncFirestore(productsRef, products);

    return {
      products
    };
}

Stop listening

var unsubscribe = db.collection("cities")
    .onSnapshot(function (){
      // ...
    });
unsubscribe();

Get All

db.collection("cities").get().then(function(querySnapshot) {
    querySnapshot.forEach(function(doc) {
        console.log(doc.id, " => ", doc.data());
    });
});

Add(Auto Indexing)

productsRef.add({
  name: this.form.name,
});

// hoặc

const ref = productsRef.doc();
. . . Logic here . . .
ref.set({
  name: this.form.name
})

Update : set() vs update()

update() : PATCH

productsRef.doc(this.form.id).update({
  name: this.form.name,
});

set() : PUT

productsRef.doc(this.form.id).set({
  name: this.form.name,
})

Nghĩa là nếu data = {name: ‘abc’, age: 3000}

– Sử dụng set sẽ replace hoàn toàn à trường hợp trên sẽ mất luôn age: 3000

Còn update thì vẫn còn

*setMerge == update

productsRef.doc(this.form.id).set({
  name: this.form.name,
}, {merge: true});

Delete

productsRef.doc(product.id).delete();

// hoặc
var removeCapital = cityRef.update({
    capital: firebase.firestore.FieldValue.delete()
});

Array(Alternation for Transaction)

Atomically action to the “regions” array field.

arrayUnion() : Add 

arrayRemove(): Remove

var washingtonRef = db.collection("cities").doc("DC");

washingtonRef.update({
    regions: firebase.firestore.FieldValue.arrayUnion("greater_virginia")
});

washingtonRef.update({
    regions: firebase.firestore.FieldValue.arrayRemove("east_coast")
});

Increment(Alternation for Transaction)

// Atomically increment the population of the city by 50.

washingtonRef.update({
    population: firebase.firestore.FieldValue.increment(50)
});

*Nếu field không tồn tại hoặc dataType != numeric => Vẫn set giá trị đã cho

Timestamp

// Update the timestamp field with the value from the server

var updateTimestamp = docRef.update({
    timestamp: firebase.firestore.FieldValue.serverTimestamp()
});

//Returns a sentinel used with set() or update() to include a server-generated timestamp in the written data.


firebase.firestore.Timestamp.fromDate(new Date());
firebase.firestore.Timestamp.now()

Converter

class City {
    constructor (name, state, country ) {
        this.name = name;
        this.state = state;
        this.country = country;
    }
    toString() {
        return this.name + ', ' + this.state + ', ' + this.country;
    }
}

// Firestore data converter
var cityConverter = {
    toFirestore: function(city) {
        return {
            name: city.name,
            state: city.state,
            country: city.country
            }
    },
    fromFirestore: function(snapshot, options){
        const data = snapshot.data(options);
        return new City(data.name, data.state, data.country)
    }
}
// Set with cityConverter
db.collection("cities").doc("LA")
  .withConverter(cityConverter)
  .set(new City("Los Angeles", "CA", "USA"));

Refer

var alovelaceDocumentRef = db.collection('users').doc('alovelace');

var alovelaceDocumentRef = db.doc('users/alovelace');

Sub-Collection

var messageRef = db.collection('rooms').doc('roomA')
                .collection('messages').doc('message1');

// hoặc
var messageRef = db.doc('rooms/roomA/messages/message1');

Result from Doc

{
  metadata: {
    fromCache: false,
    hasPendingWrite: false
  },
  empty: false,
  size: 1,
  docs: [
    {
      exists: true,
      id: "luzY87lKbB87LqrqQiJ4",
      length: 1,
      metadata: {
        fromCache: false,
        hasPendingWrite: false
      },
      ref: {
        firestore: object,
        id: String,
        parent: Object,
        path: "products/luzY87lKbB87LqrqQiJ4"
      },
      
    }
  ]
}

Important: As explained above under Events for local changes, you will receive events immediately for your local writes. Your listener can use the metadata.hasPendingWrites field on each document to determine whether the document has local changes that have not yet been written to the backend.

Query

var citiesRef = db.collection("cities");

citiesRef.doc("SF").set({
    name: "San Francisco", state: "CA", country: "USA",
    capital: false, population: 860000,
    regions: ["west_coast", "norcal"] });

Compare

citiesRef.where("state", "==", "CA")
citiesRef.where("population", "<", 100000)
citiesRef.where("name", ">=", "San Francisco")

// Compound equality queries
citiesRef.where("state", "==", "CO").where("name", "==", "Denver")
citiesRef.where("country", "==", "USA")
         .where("capital", "==", false)
         .where("state", "==", "CA")
         .where("population", "==", 860000)

In / not-in

citiesRef.where('country', 'in', ["USA", "Japan", "China"])

citiesRef.where('country', 'not-in', ["USA", "Japan", "China"])

array-contains / array-contains-any

citiesRef.where("regions", "array-contains", "west_coast")

citiesRef.where("regions", "array-contains-any", ["west_coast", "east_coast"])

Order By

citiesRef.where("country", "==", "USA").orderBy("population", "desc")

citiesRef.where("country", "==", "USA")
         .where("population", "<", 3800000)
         .orderBy("population", "desc")

*If you include a filter with a range comparison (<<=>>=), your first ordering must be on the same field:

citiesRef.where("population", ">", 100000).orderBy("population")

Collection Group

var landmarksGroupRef = db.collectionGroup("landmarks");

landmarksGroupRef.where("category", "==", "park")
landmarksGroupRef.where("category", "in", ["park", "museum"])

Pagination

// store last document
let lastestDoc = null;

const getNextReviews = async function() {
    const ref = db.collection('reviews')
        .orderBy("createdAt")
        .startAfter(lastestDoc || 0)
        .limit(6);
    const data = await ref.get();

    if(data.empty) {
        console.log("No more data to bring up !")
        return;
    }

    // update lastest doc
    lastestDoc = data.docs[data.docs.length - 1];

    let template = "";
    data.docs.forEach(doc => {
        const review = doc.data();
        template += `
            <div class="card">
                <h2>${review.title}</h2>
                <p>Writtern by ${review.author}</p>
                <p>Rating -  ${review.rating} / 5</p>
            </div>
        `
    })

    container.innerHTML = template;
}

window.addEventListener("DOMContentLoaded", () => getNextReviews());

Transaction

var sfDocRef = db.collection("cities").doc("SF");

// sfDocRef.set({ population: 0 });

return db.runTransaction(function(transaction) {
    return transaction.get(sfDocRef).then(function(sfDoc) {
        if (!sfDoc.exists) {
            throw "Document does not exist!";
        }

       
        var newPopulation = sfDoc.data().population + 1;
        transaction.update(sfDocRef, { population: newPopulation });
    });
}).then(() => {   }).catch(() => { });

Batch

var batch = db.batch();

var nycRef = db.collection("cities").doc("NYC");
batch.set(nycRef, {name: "New York City"});

var sfRef = db.collection("cities").doc("SF");
batch.update(sfRef, {"population": 1000000});

var laRef = db.collection("cities").doc("LA");
batch.delete(laRef);

batch.commit().then(function () {
    // ...
});
Published inFirestore

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *