Cloud Firestore subcollection syntax in Web version 9 API - javascript

I'm trying to learn Firestore Cloud 9 using a tutorial written for Web version 8. I am stuck trying to refactor what appears to be a subcollection of some sort.
The Web 8 code looks like this:
const ref = firestore.collection('users').doc(auth.currentUser.uid).collection('posts');
const query = ref.orderBy('createdAt');
const [querySnapshot] = useCollection(query);
My (failed) attempt looks something like this:
import { firestore, auth, serverTimestamp } from "#/lib/firebase";
import { collection, getDocs, orderBy, query } from "firebase/firestore";
import { useRouter } from "next/router";
import { useCollection } from "react-firebase-hooks/firestore";
const ref = collection(firestore, 'users');
const q = query(
ref,
where('username', '==', auth.currentUser.uid),
orderBy('createdAt', 'desc')
);
//const newPosts = (await getDocs(q)).docs.map((doc) => doc.data());
const [querySnapshot] = useCollection(q);
I can get the first collection without issue. However grabbing the subcollection (?) via the doc(ument) isn't something I can figure out. I've tried getDocs() (commented out, above) as well as getDoc() & .doc.

This line in the v8 and before syntax:
const ref = firestore.collection('users').doc(auth.currentUser.uid).collection('posts');
Will look like this in v9 and later:
const ref = collection(firestore, 'users', auth.currentUser.uid, 'posts');

Related

array-contains-any not working with orderBy and ">= <=" on Firestore

I've been struggling with Firestore queries.
This is my structure:
I'm simply trying to fetch data where any item of a set of categories belongs to any entry.
So, I'm doing something like it:
firebaseQuery(
entriesRef,
where("categories", "array-contains-any", ["link"])
where("date", ">=", "{SOME DATE BEFORE 01/01/2023}")
orderBy("date", "desc")
)
But result is always empty. Any idea of what could going on?
Thanks!
EDIT
Important information, I've made some tests and seems the getDocs(query) promise is never resolved or rejected (according to logs)
First I didn’t find any firebaseQuery in docs so I have recreated the setup from the provided code and just replaced the firebaseQuery with a query from the official firebase/firestore package.
Here’s the updated code :
import { collection, getDocs, orderBy, query, where } from "firebase/firestore";
import { db } from "./firebase.js";
const ref = collection(db, "entries");
const start = new Date();
console.log(start);
const q = query(
ref,
where("categories", "array-contains-any", ["link"]),
where("date", ">=", start),
orderBy("date", "desc")
);
const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
console.log(doc.id, " => ", doc.data().categories, doc.data().date.toDate());
});

Firebase realtime db limitToFirst(10) doesnt working

i am facing issue i am trying to get only 10 data from firebase but how can i achieve that if ref(database, "messages/").limitToFirst(10) is throwing:
ref(...).limitToFirst is not a function
My code:
const newMsg = ref(database, 'messages/').limitToFirst(10);
onChildAdded(newMsg, (data) => {
if(data.val().name != name){
var divData = '<div class="message"><div class="others">'+data.val().name+': </div><div>'+data.val().message+'</div></div>';
//oponent message
$("#chat-history").append(divData);
}else{
var divData = '<div class="message"><div class="user">'+data.val().name+': </div><div>'+data.val().message+'</div></div>';
//sent message
$("#chat-history").append(divData);
}
});
Where database is
const app = initializeApp(firebaseConfig);
const database = getDatabase(app);
And my imports look like this:
import {initializeApp} from "https://www.gstatic.com/firebasejs/9.6.6/firebase-app.js";
import {
getDatabase,
set,
ref,
push,
child,
onValue,
onChildAdded
} from "https://www.gstatic.com/firebasejs/9.6.6/firebase-database.js";
EDIT:
After a hour i see where is the problem in my import i need to add query, limitToLast
import {
getDatabase,
set,
ref,
query,
push,
child,
onValue,
onChildAdded,
limitToLast
} from "https://www.gstatic.com/firebasejs/9.6.6/firebase-database.js";
And in my function just call it like this:
const newMsg = query(ref(database, 'messages/'), limitToLast(10));
onChildAdded(newMsg, (data) => {
In the new Modular SDK (v9.0.0+), you can build a Query using query() function (instead of chaining the QueryConstraints):
import { ref, query, limitToFirst } from "firebase/database"
const newMsg = query(ref(database, 'messages/'), limitToFirst(10))
onChildAdded(newMsg, (data) => {
// ...
})
The new SDK uses a functional syntax unlike the older name-spaced one so limitToFirst is a top-level function now as in above code snippet.
Also checkout:
How to read, write and query data in Firebase Realtime Database using Firebase SDK v9 (Modular)
Working with lists of data

Reducing Firebase SDK bundle size?

I've used the new tree-shakeable version of Firebase SDK, which still seems to produce quite a large chunk, considering what I use it for.
I only use the Firestore part, and have actually moved all Firestore operations to the backend, the only thing I'm doing on the front end is initiating the Firebase app instance and starting a snapshot listener (due to the real-time ability), yet the bundle produced is still 275kb large.
import { initializeApp } from 'firebase/app'
import { getFirestore, collection, doc, onSnapshot, query, where, orderBy } from 'firebase/firestore'
const documents = ref(null)
const firebaseApp = initializeApp(firebaseConfig)
const db = getFirestore(firebaseApp)
const ref = query(collection(db, 'documents'), where(`something`, '==', 'something'), orderBy('createdAt', 'desc'))
const unsub = onSnapshot(ref, (snap) => {
let results = []
snap.docs.forEach(el => {
el.data().createdAt && results.push({ ...el.data(), id: el.id })
})
documents.value = results
}, err => {
console.log(err.message)
documents.value = null
})
Is there a way to reduce that size slightly, without sacrificing the real-time ability?

how to write firebase v8 code using firebase v9

This code block is written in Firebase v8 syntax but how to write this code using firebase v9?
You need to check the Firebase documentation for the upgrade to V9, and you need update your library react-firebase-hooks to 4.0.0 version (here documentation).
In your example, it would look like this:
import { useCollection } from 'react-firebase-hooks/firestore'
import { getFirestore, collection, query, where } from 'firebase/firestore'
const db = getFirestore(firebaseApp);
const q = query(collection(db, 'chats'), where('users', 'array-contains', user.email));
const [value, loading, error] = useCollection(
q,
{ snapshotListenOptions: { includeMetadataChanges: true } }
)

Valid way to delete a doc from firebase

I want to delete a game from my firestore collection, but i get error:
TypeError: doc is not a function
I am using the latest version of Firebase. What is the proper way to delete the doc?
import {where,query,deleteDoc,collection, doc, getDocs, getFirestore } from "firebase/firestore";
deleteGame(game) {
const db = getFirestore();
const q = query(collection(db, "history"), where("date", "==", game.date));
const doc = getDocs(q);
const quer = await getDocs(q);
quer.forEach((doc) =>
{
deleteDoc(doc(db, "history", doc.id));
});
}
According to firebase documentation for delete data you should indeed use
deleteDoc(doc(db, "history", doc.id));
But doc needs to be the function imported from firebase/firestore . You are rewriting the value of doc with the element from quer ( quer.forEach((doc) => ).
You also have const doc = getDocs(q); so you will need change the name of both doc variables in order to use the imported function inside the forEach callback.
Also keep in mind that this won't subcollections (if you have any - as specified in the docs).

Categories