Collection references must have an odd number of segments - javascript

I am currently encountering this problem in my react native app using Firebase:
Collection references must have an odd number of segments
I've seen similar cases in stackoverflow but wasn't able to solve my problem. Here is my code :
const getData = async () => {
console.log(user.uid + " 🚧🚧🚧")
const col = collection(db, "users", user.uid)
const taskSnapshot = await getDoc(col)
console.log(taskSnapshot)
}
getData()
I am trying to open my document with the document reference (user.uid) but I am getting this error : Collection references must have an odd number of segments
Hope you can help me solve this problem.

The getDoc() takes a DocumentReference as parameter and not a CollectionReference so you must use doc() instead of collection().
import { doc, getDoc } from "firebase/firestore"
const docRef = doc(db, "users", user.uid)
const taskSnapshot = await getDoc(col)
console.log(taskSnapshot.data() || "Doc does not exists")
Also checkout Firestore: What's the pattern for adding new data in Web v9?

replace this
collection(db, "users", user.uid)
with this
collection(db).document("users").collection(user.uid)

Related

React Firestore get id when creating document [duplicate]

Heres what i am trying to achieve i want a unique id field for every document in my database and i want that unique id to the same as the document id.
Example:
documents: data:
eBgdTRE123 id:'eBgdTRE123'
name:'Jhon Doe'
job:'Programmer'
i want i databse to have this structure, now i got two ideas to achieve this
1: to use cloud function and have onCreate listener and everytime theres a new document grab document and set the id field and update it heres how i am doing it
exports.addDocIdToField =
functions.firestore.document('collectionname/{docID}').onCreate((snap,context) => {
const id = context.params.docID;
return admin.firestore().collection('collectionname')
.doc(id).set({ id: snap.id }, { merge: true })
.then(() => {
return null;
})
.catch((error) => {
return null;
});
})
2: to use the above kind of method on document creation. add a new document as soon as that document is added get the newly added document and update its id
both of them work but my question is can i rely on this kind of operation? i mean if the id is by any means undefined it can cause an error further in the app.
or if there are other ways to achieve this?
See JS SDK v9 syntax at the bottom
There is a simpler way to achieve that, using the doc() method, as follows (here with the JavaScript SDK v8)
var newDocRef = db.collection('collectionname').doc();
newDocRef.set({
name:'Jhon Doe',
job:'Programmer',
id: newDocRef.id
})
As explained in the doc:
(the doc() method) gets a DocumentReference for the document within the collection at the
specified path. If no path is specified, an automatically-generated
unique ID will be used for the returned DocumentReference.
You will find similar methods in the other Client SDKs, here for Android and here for iOS.
UPDATE FOR JS SDK v9:
import { collection, doc, setDoc } from "firebase/firestore";
const newDocRef = doc(collection(db, "collectionname"));
await setDoc(
newDocRef,
{
name:'Jhon Doe',
job:'Programmer',
id: newDocRef.id
}
)
the previous method works fine but just for the sake of clarification
what is it really like
const { doc, collection, getFirestore, setDoc, addDoc } = require('firebase/firestore');
let collectionId = "Cars";
let docId;
let firestore = getFirestore();
async function addDocWithId() {
let collectionRef = collection(firestore, collectionId)
addDoc(collectionRef, {}).then(res => {
docId = res.id
let docRef = doc(firestore, collectionId + "/" + docId)
setDoc(docRef, {
id: docId,
car: 'Benz'
})
})
};
how it has been clarified
const { doc, collection, getFirestore, setDoc, addDoc } = require('firebase/firestore')
let collectionId = "Cars"
let firestore = getFirestore()
async function addDocWithId() {
let collectionRef = collection(firestore, collectionId)
let docRef = doc(collectionRef)
setDoc(docRef, {
id: docRef.id,
car: "Volvo"
})
}
If in case if there's anyone who didn't have luck with above provided answers, try this -> docref.set({ 'id':docref.ref.id}). It worked for me. Below is a usecase of this.
create(tutorial: any): any {
var docref = this.db.collection('invxxx').doc()
docref.set({ 'id':docref.ref.id, anotherField: 'anotherValue'});
}

getDoc from firestore without searching for specific uid

I'm having an issue getting the collection info. Using this code, I could only get the doc with a specific uid.
const snapShot = doc(db, 'Files', 'someUID');
const getSnapShot = await getDoc(snapShot);
console.log(getSnapShot.data());
I used this code to get all of the collection items but threw an error.
const snapShot = collection(db, 'Files');
const getSnapShot = await getDoc(snapShot);
console.log(getSnapShot.forEach(doc => console.log(doc.data()));
Uncaught (in promise) FirebaseError: Expected type 'wc2', but it was: a custom gc2 object
Q: How do I make it work?
To get all documents from a collection or documents that match a query you should use getDocs() instead of getDoc() that is used to fetch a single document as the function name suggests.
const snapShot = collection(db, 'Files');
const getSnapShot = await getDocs(snapShot);
console.log(getSnapShot.forEach(doc => console.log(doc.data()));

Converting firebase 8 code to firebase 9 code (web, javascript) to fetch collection within collection

Hello I would like to convert the following firebase 8 code to firebase 9 and have no clue how to do it - any help would be welcome!
This piece of code should go inside the userDoc and then fetch the collection that is insdie that document and return all of the posts that belong to that user
if (userDoc) {
user = userDoc.data()
const postsQuery = userDoc.ref
.collection('posts')
.where('published', '==', true)
.orderBy('createdAt', 'desc')
.limit(5)
posts = (await postsQuery.get()).docs.map(postToJSON)
}
enter image description here
Firestore's documentation has examples for both V8 and V9 so you can easily compare them and modify your code. Just switch to modular tab for the new syntax. The code in question would be like:
import { collection, query, where, getDocs, orderBy, limit } from "firebase/firestore";
const q = query(collection(db, "posts"), where("published", "==", true), orderBy("createdAt", "desc"), limit(5));
const querySnapshot = await getDocs(q);
posts = querySnapshot.docs.map(postToJSON)

Firestore: Conditional query not executed

This logs the snapshot:
const db = firebase.firestore();
const collection = db.collection(`companies/${company}/meetings`);
let query = collection.where('start', '>=', new Date());
const snapshot = await query.limit(10).get();
console.log(snapshot);
This doesn't:
const db = firebase.firestore();
const collection = db.collection(`companies/${company}/meetings`);
let query = collection.where('start', '>=', new Date());
if (branch) {
query = query.where('branch', '==', branch);
}
const snapshot = await query.limit(10).get();
console.log(snapshot);
Does anyone know why?
Since you are combining the '>=' and '==' operators, Firestore needs to build an index for this query.
If you catch the error with a try/catch block, you will see the corresponding error, and, even better, the error message includes a direct link to create the missing index in the Firebase console.
See the doc here for more details on indexing in Firestore.

Querying by a field with type 'reference' in Firestore

I have a collection called 'categories' containing a single document with ID: 5gF5FqRPvdroRF8isOwd.
I have another collection called 'tickets'. Each ticket has a reference field which assigns the ticket to a particular category.
The field in the tickets collection is called 'category' and has a field type of reference.
In the code below, categoryDocId is the document ID of the category I want to query by.
const categoryDocID = `5gF5FqRPvdroRF8isOwd`;
const files = await firebase
.firestore()
.collection('tickets')
.where('category', '==', categoryDocID)
.get();
Why does files.length return 0?
For testing, I changed the category field type to string, and set it to the category ID instead of a direct reference. This correctly returned tickets assigned to the category, which leads me to believe it's something about how I'm querying a reference field.
As you will read here in the doc, the Reference Data Type is used to store DocumentReferences.
If you want to use it in a query, you cannot use a simple string, neither the UID of the document (i.e. '5gF5FqRPvdroRF8isOwd'), nor the string value that is stored in the field (i.e. '/categories/5gF5FqRPvdroRF8isOwd').
You have to build a DocumentReference and use it in your query, as follows:
JS SDK V9
import { doc, query, collection, where, getDocs } from "firebase/firestore";
const categoryDocRef = doc(db, "categories", "5gF5FqRPvdroRF8isOwd");
const q = query(
collection(db, "tickets"),
where("category", "==", categoryDocRef)
);
const files = await getDocs(q); // !! files is a QuerySnapshot
JS SDK V8
const categoryDocRef = firebase.firestore()
.collection('categories')
.doc('5gF5FqRPvdroRF8isOwd');
const files = await firebase // !! files is a QuerySnapshot
.firestore()
.collection('tickets')
.where('category', '==', categoryDocRef)
.get();
With Firebase Version 9 (Dec, 2021 Update):
You must make a document reference with "categories/5gF5FqRPvdroRF8isOwdand" then use it in your query:
import { doc, query, collection, where, getDocs } from "firebase/firestore";
const categoryDocRef = doc(db, "5gF5FqRPvdroRF8isOwd");
const q = query(
collection(db, "tickets"),
where("category", "==", categoryDocRef)
);
const ticketDocsSnap = await getDocs(q);
Here is how I use reference type to query a collection (node.js + typescript):
let myCollectionADocument = await admin.firestore().collection("collection_a").doc("documentId").get();
let myCollectionB = await admin.firestore().collection("collection_b").where("collection_a_id", "==", myCollectionADocument.ref).get();

Categories

Resources