How to get a single doc with React/Firestore? - javascript

All I want to do is to get a row (so called 'doc') from a data base.
so far, I have tried:
all with the 'aref'
const aref = firebase
.firestore()
.collection("polja")
.where("id", "==", match.params.id);
console.log(aref);
function getIt() {
const item = [];
setLoading(true);
aref.get().then((doc) => {
const data = doc.data();
setItem(item);
console.log(item);
setLoading(false);
});
}
useEffect(() => {
getIt();
}, []);
this gave the following error:

To get a single document, you must specify the document ID:
firebase.firestore().collection("polja").doc(documentId).get().then((snapshot) => {
console.log(snapshot.data())
}).catch((e) => console.log(e))
Also you should not use .where() to get just a single document, but there is an issue I found in your original code.
If you look carefully, the parameter in .where() is a string "match.params.id". That seems to be a dynamic value being fetched from somewhere else. Please remove the quotes and try again.
firebase.firestore().collection("polja").where("id", "==", match.params.id).get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data());
});
})
.catch((error) => {
console.log("Error getting documents: ", error);
});
Try adding a catch block as shown which might help catch any errors. Make sure your security rules also allow you to fetch the data.
Also if any error is logged in the console, share a screenshot of it.

To get single document form firebase firestore you should first know if you are using the modular firebase 9.+ version or firebase version < 9.
In new modular firebase firestore(version 9.+) it should be like this:
import { getFirestore, collection, query, getDocs } from 'firebase/firestore'
async read(id) {
const firestore = getFirestore()
const docRef = doc(firestore, this.collectionPath, id)
const docSnap = await getDoc(docRef)
const data = docSnap.exists() ? docSnap.data() : null
if (data === null || data === undefined) return null
return { id, ...data }
}
If you are using not modular Firebase firestore( < version 9) then the same function should look something like this:
async read(id) {
const result = await (await firestore())
.collection(this.collectionPath)
.doc(id)
.get()
const data = result.exists ? result.data() : null
if (data === null || data === undefined) return null
return { id, ...data }
}

Related

How to query in a specific document in Firebase

I have some code that gets a collection reference to the users collection and then queries an animeID field whether it contains a certain value or not. I want to change this and only query inside the document with the id i pass. So if you look at the picture of my firestore you can see that i have two documents inside the users collection each with their unique id. I want to query for the animeID field only in the document that i want. Not all the documents as it does right now. How would i go about doing this? I have tried using doc and then passing in the id of the document but i don't think query works on doc as it gives me an error. Thanks
const docRef = collection(db, 'users')
const q = query(docRef, where('animeID', 'array-contains', parseInt(id)))
onSnapshot(q, (snapshot) => {
let results = []
snapshot.docs.forEach((doc) => {
results.push({...doc.data(), id: doc.id})
})
if(results.length > 0){
console.log(true)
}
else{
console.log(false)
}
}, (error) => {
console.log(error)
})
Firestore structure:
You need to do as explained in the doc:
import { doc, getDoc } from "firebase/firestore";
const docRef = doc(db, "users", "dbmbEiR6....");
const docSnap = await getDoc(docRef);
if (docSnap.exists()) {
const animeID = docSnap.data().animeID;
// Do whatever you want with animeID
// E.g. log its value:
console.log(JSON.stringify(animeID));
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
So you don't need to declare a Query in this case. Just declare a DocumentReference and use the getDoc() method.

Attempting to use equalTo on Firebase Realtime Database query

I have the following node:
attendanceOptions: {
uid1: 'blah#example.com',
uid2: 'tap#example.com'
}
I'm trying to return only the key and value where value is equal to. These are my two attempts.
const getMinistry = await admin.database().ref(`organization/${req.orgId}/attendanceOptions`)
getMinistry
.equalTo(req.memberUid)
.once('value', snapshot => {
functions.logger.log(snapshot.val())
});
This returns null
I also tried:
const getMinistry = await admin.database().ref(`organization/${req.orgId}`)
getMinistry
.orderByChild('attendanceOptions')
.equalTo(req.memberUid)
.once('value', snapshot => {
const data = snapshot.val();
functions.logger.log( `this is data: ${data}` )
return data;
});
The log is this is data: null
In my rules I have:
"attendanceOptions": {
".indexOn": [".value"]
},
What am I doing wrong here?
The correct syntax is:
getMinistry
.child('attendanceOptions')
.orderByValue()
.equalTo(req.memberUid)

getDocs - firebase react native

I want to get a document and to update.
I tried used this code, but he dont accept the "idDoc":
const Doc = query(collection(database, "user_veic"),where("email", "==", auth.currentUser?.email),where("kmF", "==", ""));
getDocs(Doc).then((querySnapshot) => {
querySnapshot.forEach((doc) => {
console.log(`${doc.id} => ${doc.data()}`);
const idDoc = doc.id
})
})
.then(
updateDoc(doc(database, "user_veic", idDoc), {
kmF: "teste1",
km: "teste1",
}))
^^^^: FirebaseError: Invalid document reference. Document references must have an even number of segments, but user_veic has 1
I tried this:
const Doc = query(collection(database, "user_veic"),where("email", "==", auth.currentUser?.email),where("kmF", "==", ""));
getDocs(Doc).then((querySnapshot) => {
querySnapshot.forEach((doc) => {
console.log(`${doc.id} => ${doc.data()}`);
const idDoc = doc(database, "user_veic", doc.id)
updateDoc(idDoc, {
kmF: "teste1",
km: "teste1",
})
})
})
^^^^: [Unhandled promise rejection: TypeError: doc is not a function. (In 'doc(database, "user_veic", doc.id)', 'doc' is an instance of lh)]
What did i do wrong?
In your first code example, you declare const idDoc inside of the callback parameter to .forEach(). That variable does not exist outside of the callback function. You then try to use it in the updateDoc() in a completely different block of code. It is undefined at that point, thus you are getting an error that you aren't passing enough parameters.
In your second code example, which is much closer to what you want to do, based on the error message it looks like you aren't importing doc with the rest of the Firestore functions from firebase/firestore.
RESOLVIDO #Greg thank you
const Doc = query(collection(database, "user_veic"),where("email", "==", auth.currentUser?.email),where("kmF", "==", ""));
getDocs(Doc).then((querySnapshot) => {
let values = null;
querySnapshot.forEach((doc) => {
console.log(`${doc.id} => ${doc.data()}`);
values = doc.id;
});
var transactionUpdate = database.collection("user_veic").doc(values);
transactionUpdate.update({
kmF: kmF,
})
})

how to remove an array item from firestore using JavaScript?

I'm trying to add a delete button to my page. the event listener callback is working properly except for the updateDoc function.
const deleteBook = document.getElementsByClassName('deleteBook');
for (let i = 0; i < deleteBook.length; i++) {
deleteBook[i].addEventListener('click', async () => {
//book to delete
const bookToDelete = deleteBook[i].parentElement.firstElementChild.textContent
// collection title to delete the book from
const bookCol = deleteBook[i].parentElement.parentElement.parentElement.firstElementChild.textContent
// get a snap of the database
const docRef = doc(dataBase, 'users', `${auth.currentUser.uid}`)
const docSnap = (await getDoc(docRef)).data();
// loop over the collections and get a match with the bookCol
for (const col in docSnap) {
if (docSnap[col].title === bookCol) {
console.log('col to delete from found')
console.log(`book to delete ${bookToDelete}`)
await updateDoc(doc(dataBase, 'users', `${auth.currentUser.uid}`), {
[`${col}.books`]: arrayRemove(`${bookToDelete}`)
}).then(()=>{
// fullfiled
console.log('book deleted')
}, ()=>{
// rejected
console.log('promis rejected')
})
}
}
})
}
Col is the object that contains the books array. In the console it always prints book deleted, but in the firestore console, nothing changes. this is a screenshot of the database.
I would really appreciate any help and thank you.
I have replicated the behavior that you're experiencing. I tried changing the content of ${bookToDelete} to any word or even ID. It always returns book deleted even if its deleted or not. The line of code below should be changed in order to get the correct output.
.then(()=>{
// fullfiled
console.log('book deleted')
}, ()=>{
// rejected
console.log('promis rejected')
})
I have created a workaround for your use-case with this kind of issue. See snippet below:
const db = getFirestore();
const colName = "users";
const arrayName = "books";
const usersCol = collection(db, colName);
const userRef = doc(db, colName, `${auth.currentUser.uid}`);
const arrayRef = `${col}.${arrayName}`;
const q = query(usersCol, where(arrayRef, "array-contains", `${bookToDelete}`));
const querySnapshot = await getDocs(q)
.then((querySnapshot) => {
// Removal of object will not proceed if the querySnapshot is empty.
if ((querySnapshot.empty)) {
console.log("No object found!");
}
else {
// Proceeds to removal of object.
updateDoc(userRef, {
[arrayRef]: arrayRemove(`${bookToDelete}`)
})
.then(() => {
// Check again if the object was deleted successfully.
const querySnapshot = getDocs(q)
.then((querySnapshot) => {
if ((querySnapshot.empty)) {
console.log("Book Deleted!");
}
else {
console.log("Failed!");
}
})
});
}
})
// Catch if there are any Firebase errors.
.catch(error => console.log('Failed!', error));
The workaround that I created will query the object in the array then remove the object in the array if it exist. After removing, it will query again to check if the object has been deleted and logs Book Deleted!. Vise versa for checking if the object doesn't exist on the 1st query, it will not proceed on removing them and logs No object found!.
The workaround itself can still be improved. You can add any logic you want for your use-case.
I'd also recommend to create a Feature Request if you want to have this kind of feature together with the arrayRemove Method.

Reading a value from Realtime Firebase

I have the following json structure:
Within "all" node I have an attribute "drinkId" and I'm trying to move it outside that child node bringing it one level up.
I'm trying to read the value without any luck
const cocktailRef= firebase
.database()
.ref("Ratings");
cocktailRef.once("value", (snapshot) => {
snapshot.forEach((child) => {
const drinkIdPass = child.ref.child("all").child("drinkId").value();
child.ref.update({ drinkId: drinkIdPass });
})
})
I've tried different variants of ".value()", same problem
There isn't any value() method on a DataSnapshot. It's val() Try refactoring your code like this:
const cocktailRef= firebase.database().ref("Ratings");
cocktailRef.once("value").then(async (snapshot) => {
const updates = { }
snapshot.forEach((child) => {
const drinkIdPass = child.val().all.drinkId
updates[`${child.key}/drinkId`] = drinkIdPass
})
await cocktailRef.update(updates)
console.log("Data updated")
})

Categories

Resources