Why error Expected first argument to collection() to be a CollectionReference - javascript

I am getting the following error when trying to get all documents from a collection in Firestore using firebase admin SDK:
[nuxt] [request error] Expected first argument to collection() to be a
CollectionReference, a DocumentReference or FirebaseFirestore
I am testing via a simple console.log:
/server/api/posts.js:
import { firestore } from '../utils/firebase'
import { collection, getDocs } from 'firebase/firestore'
export default defineEventHandler(async (event) => {
const colRef = collection(firestore, 'posts')
console.log(colRef)
})
Here is how I am initializing firestore:
/server/utils/firebase.js:
import { initializeApp, cert } from 'firebase-admin/app'
import { getFirestore } from 'firebase-admin/firestore'
import serviceAccount from '../../service-account.json'
export const app = initializeApp({
credential: cert(serviceAccount)
})
export const firestore = getFirestore()
Note: The following code works on the server-side and I am able to get a document back, but for some reason I can't use the collection() like in the above example.
import { firestore } from '../utils/firebase'
export default defineEventHandler(async (event) => {
const ref = firestore.doc(`animals/dog`)
const snapshot = await ref.get()
const data = snapshot.data()
console.log(data)
// return {
// data
// }
})
Also, if I run the collection() function on the client side, I can successfully retrieve the posts. I just can't figure out why it won't work server-side.
Anyone know why I get the above error?

None of the server code you have shared align to such an error message. The error indicates that you are calling .get() or .onSnapshot() with something that is not a DocumentReference or a CollectionReference.
Note: collection() and doc() are functions that return References. They don't actually communicate to the FS service...a Reference is (essentially) a string such as `/posts' or '/posts/1234567'
So, somewhere in your code, you need to find where it is hitting the above error and either share it here or understand why what you are calling it on is not a valid CollectionReference or DocumentReference.

Related

Cloud Firestore subcollection syntax in Web version 9 API

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');

Error retrieving data from Firebase database

I'm trying to sync my app to a firebase database to retrieve some data. With the code below, I'm able to console log 'polls' which is a basic collection I made in Firebase, and I can see all my data in the console log.
But if I actually try to reach into the polls object using polls.data.id or polls.data.label or even just polls.data, the page blanks out and I get an error saying that it "Cannot read the properties" that I'm calling for. Any help would be greatly appreciated!
import { useEffect, useState } from "react"
import { collection, getDocs } from "firebase/firestore"
import { db } from '../firebase.config'
function Food() {
const [polls, setPolls] = useState([])
useEffect(() => {
getPolls()
}, [])
useEffect(() => {
console.log(polls.data.id);
}, [polls])
function getPolls() {
const pollsRef = collection(db, 'polls');
getDocs(pollsRef).then(response => {
const poll = response.docs.map(doc => ({data: doc.data(), id: doc.id}))
setPolls(poll)
}).catch(error => console.log(error.message))
}
return (
<div>
Food
</div>
)
}
export default Food
Since my app is clearly fetching the object properly, I'm not sure why I'm not able to actually retrieve the data from within the object to use in my app.
Your polls is an array, so you can't just console.log(polls.data.id). Since polls is an array, it has no data attribute, and thus you can't call id on that, which is what the error says.
Instead, loop over the results with:
useEffect(() => {
polls.forEach((pol) =>
console.log(poll.id);
})
}, [polls])
Note that I also console.log(poll.id), since you map the ID to the object itself, not in its data property.

Firebase - How can i get data from reference?

I have a firebase firestore with some reference datatype.
It looks like this:
I Hope, this is the correct way.
Now when i get my user from firebase, i have this reference object with the id of it.
But if i call my function to get the doc, i get an error message:
First my function and how i call it:
export const getClubById = async (id: string) => {
const doc = collection(db, 'clubs', id)
return doc
}
const userData = dbUser.data()
const club = await getClubById(userData.selectedClub.id)
console.log('club', club)
And here the error message:
Uncaught (in promise) FirebaseError: Invalid collection reference. Collection references must have an odd number of segments, but clubs/vA7R94pX3bpHDsYIr6Ge has 2.
If you have the DocumentReference already then you can use getDoc() function to retrieve the document from Firestore as shown below:
import { getDoc, DocumentReference } from "firebase/firestore";
export const getClubById = async (clubDocRef: DocumentReference) => {
const clubSnapshot = await getDoc(clubDocRef);
return clubSnapshot.data();
}
// Pass the reference itself to the function instead of doc ID
const club = await getClubById(userData.selectedClub)
For the error in the question, to create a DocumentReference, if you have the document ID then you should doc() function instead of collection() that is used to create a CollectionReferencce as shown below:
const docRef = doc(db, 'clubs', clubID);
Also checkout: Firestore: What's the pattern for adding new data in Web v9?

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

How to get a Subcollection inside a Collection in Firestore Web Version 9 (Modular)?

I was using the chaining mode of the Firestore Web 8, but I'm in the way of updated it to Module 9 and have been a hard time trying to figure out how to get all the content of my subcollection (collection inside my collection).
My older function is like this and works fine:
function getInfo(doc_name) {
let infoDB = db
.collection("collection_name")
.doc(doc_name)
.collection("subcollection_name")
.get();
return alunoHistorico;
}
so with the module way I tried this code
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const db = getFirestore(app);
const docRef = doc(db, "collection_name", "doc_name");
const docSnap = await getDoc(docRef);
if (docSnap.exists()) {
console.log("Document data:", docSnap.data());
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
but the function doc() expects a even arguments (not counting the db argument) so if I try to use with 3 arguments like this, I get a error:
const docRef = doc(db, "collection_name", "doc_name", "subcollection_name");
to it work I have to pass the exactly document that is inside the subcollection
const docRef = doc(db, "collection_name", "doc_name", "subcollection_name", "sub_doc");
but it doesn't work for me because I have a list os docs inside the subcollection, that I want o retrieve.
So how can I get all my docs inside my subcollection?
Thanks to anyone who take the time.
You need to use collection() to get a CollectionReference instead of doc() which returns a DocumentReference:
const subColRef = collection(db, "collection_name", "doc_name", "subcollection_name");
// odd number of path segments to get a CollectionReference
// equivalent to:
// .collection("collection_name/doc_name/subcollection_name") in v8
// use getDocs() instead of getDoc() to fetch the collection
const qSnap = getDocs(subColRef)
console.log(qSnap.docs.map(d => ({id: d.id, ...d.data()})))
I wrote a detailed answer on difference between doc() and collection() (in V8 and V9) here:
Firestore: What's the pattern for adding new data in Web v9?
If someone want to get realtime updates of docs inside sub collection using onSnapshot in Modular Firebase V9, you can achieve this like:
import { db } from "./firebase";
import { onSnapshot, collection } from "#firebase/firestore";
let collectionRef = collection(db, "main_collection_id", "doc_id", "sub_collection_id");
onSnapshot(collectionRef, (querySnapshot) => {
querySnapshot.forEach((doc) => {
console.log("Id: ", doc.id, "Data: ", doc.data());
});
});

Categories