Im having a bunch of documents in a collection in firestore. What I want to archieve is to search the documents by a "timestamp" property, after that I want to delete exactly this document.
My code looks right now like this:
firebase.firestore().collection("chatrooms").doc(`${chatId}`).collection(`${chatId}`).where("timestamp", "==", timekey).get().then((QuerySnapshot) => {
if (!QuerySnapshot.empty) {
QuerySnapshot.forEach((doc)=>{
console.log(doc.data().value)
});
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
});
It is not deleting anything yet, its only returning me the value of the found document in my collection so I can see if the .where() call even works. Im having trouble to combine this .where() together with .delete() and I am not even sure if that is possible. Does anybody have any idea how to accomplish this task?
I can't see .delete() in your code. Also you cannot combine .delete() and .where(). You need the document IDs or the references to them. You can try this:
firebase.firestore().collection("chatrooms").doc(chatId).collection(chatId).where("timestamp", "==", timekey).get().then((QuerySnapshot) => {
if (!QuerySnapshot.empty) {
const deleteDocs = []
QuerySnapshot.forEach((doc)=>{
console.log(doc.data().value)
deleteDocs.push(doc.ref.delete())
});
Promise.all(deleteDocs).then(() => {
console.log("Docs delete")
}).catch(e => console.log(e))
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
});
PS: You don't need to use Template Literals [${} thing] if you just have one variable.
You can directly pass the var as .doc(chatId)
Related
I am using react-native and I want to get specific data so I used a query, the problem is that it didn't work, but if I remove the where and do an if statement it works. How can I fix this ?
This is my implementation:
let query = firestore().collection('conversations');
query = query.where('users', 'array-contains', myId);
// query = query.where('postId', '==', postId);
query
.orderBy('timestamp', 'desc')
.limit(limit)
.get()
.then((snapshot) => {
const offersObjects = {};
if (snapshot.docs.length) {
snapshot.docs.forEach((doc) => {
if (postId === doc.data().postId) {
offersObjects[doc.id] = { ...doc.data(), pendingMessages: [] };
}
});
dispatch({
type: chatTypes.SET_OFFERS,
payload: { offers: offersObjects },
});
}
})
Where the code is commented is where this query doesn't work which is weird since the one above it works fine. How can I fix this ?
If you have more than one condition on a query, it may need a composite index that is not automatically created. If that is the case, executing the query (e.g. by calling get() on it) will raise an error, but you'r not hancling errors. I recommend adding a catch clause after your then and logging the error.
If the problem is caused by a missing index, the error message contains a URL that opens the Firebase console on the page to create the exact index that is needed, with all fields already filled in. Create the index, wait for it to be completely created, and run the query again.
I have a Firestore collection called Posts, and each document in Posts could have a sub-collection called Post-Likes and/or Post-Comments. When I delete the Posts document, it does not delete the sub-collection so I am left with a reference to a missing document in Firestore which looks like this:
I am using the following code in my Google Cloud Function to find references in the Post collection with missing data, then for each document with a missing reference, I want to delete the sub-collections Post-Likes and Post-Comments. For now, I am just try to list the sub-collection document so I can delete them, but I am getting an error.
function deleteOrphanPostSubCollections() {
let collectionRef = db.collection('Posts');
return collectionRef.listDocuments().then(documentRefs => {
return db.getAll(...documentRefs);
}).then(documentSnapshots => {
for (let documentSnapshot of documentSnapshots) {
if (documentSnapshot.exists) {
console.log(`Found document with data: ${documentSnapshot.id}`);
} else {
console.log(`Found missing document: ${documentSnapshot.id}`);
return documentSnapshot.getCollections().then(collections => {
return collections.forEach(collection => {
console.log('Found subcollection with id:', collection.id);
});
});
}
}
return
});
}
However, I am getting the following error. Please help me resolve this issue.
This is because there is not getCollections() method for a DocumentSnapshot.
If you want to list all the collections of the Document corresponding to the DocumentSnapshot, you need to use the listCollections() method, as follows:
documentSnapshot.ref.listCollections()
.then(collections => {
for (let collection of collections) {
console.log(`Found subcollection with id: ${collection.id}`);
}
});
In addition, note that if you call an asynchronous method in a loop, it is recommended to use Promise.all() in order to return a single Promise that resolves when all the "input" Promises are resolved.
db.collection("rooms").add({
code: this.state.code,
words: []
}).then(() => {
db.collection("rooms").where("code", "==", this.state.code).get().then((doc) => {
doc.collection("players").add({name: this.state.name, votes: 0}).then(() => {
socket.emit("createGroup", this.state.code);
});
});
});
I am building a React/Express app using client-side Firestore calls and SocketIO. I'm getting the following error in console: "Uncaught (in promise) TypeError: t.collection is not a function". I guess the Firestore document -> {code: this.state.code, words: []} has somehow not yet been created when I reference it in the then function -> db.collection("rooms").where("code", "==", this.state.code). Any suggestions on how I can fix this error while still maintaining the order of the Firestore calls?
When you call get() on a Query object as you are here:
db.collection("rooms").where("code", "==", this.state.code).get()
It's going to return a promise that yields a QuerySnapshot object. That object does not have a method called collection() on it. It contains the results of the query that you will have to deal with.
You're going to have to iterate or otherwise handle the results of that query to move forward. Your code should also be prepared for the case that that query returns no documents. Use the docs array property on the QuerySnapshot to learn about what happened.
db.collection("rooms").where("code", "==", this.state.code).get().then(querySnapshot => {
querySnapshot.docs.forEach(snapshot => {
// handle each document individually, if any
})
});
I suggest also reviewing the documentation on Firestore queries, along with the API documentation I linked above.
db.collection("rooms").add({
code: this.state.code,
words: []
}).then(() => {
db.collection("rooms").where("code", "==", this.state.code).get().then((querySnapshot) => {
querySnapshot.docs.forEach((snapshot) => {
snapshot.ref.collection("players").add({name: this.state.name, votes: 0}).then(() => {
socket.emit("createGroup", this.state.code);
});
});
});
});
This implementation works thanks to help from Doug.
exports.getref = (oid, successFunc, errFunc) => {
dbconfig.collection('txn')
.where('oid', '==', oid)
.get()
.then(docRef => {
successFunc({
id: docRef.id,
success: true
})
})
.catch(err => {
errFunc({ id: null, success: false })
})
here I want to get document id of my collection where field value oid equals oid . how i can get doc id
When you perform a query with Firestore, you get back a QuerySnapshot object, no matter how many documents match the query.
dbconfig.collection('txn')
.where('oid', '==', oid)
.get()
.then(querySnapshot => { ... })
You have to use this QuerySnapshot to find out what happened. I suggest reading the linked API documentation for it.
You should check to see if it contains any documents at all with the size method, then if it has the document you're looking for, use the docs array to find the DocumentSnapshot with the data. That snapshot will have a DocumentReference property with the id:
if (querySnapshot.size == 1) {
const snap = querySnapshot.docs[0];
console.log(snap.ref.id);
}
else {
console.log("query result in exactly one document");
}
I am trying to fetch all fieldnames inside of payload > (random doc id) objects.
Currently I am fetching other collections with:
async fetchPage() {
const query = firebase
.firestore()
.collection('PAGES')
.where('type', '==', 'page')
try {
const { docs } = await query.get()
this.pageIndex = docs.map((doc) => {
if (doc && doc.exists) {
this.items = doc.data()
}
let { id } = doc
const data = doc.data()
return { id, ...data }
})
console.log('Loaded items', this.items)
} catch (error) {
throw new Error('Something gone wrong!')
}
},
The first question is: What is the best practice to query objects? I read this in firebase docs but didn't lead me to any results trying it out that way.
Second question, since the child object of payload is the actual id of its document, what method must I use to declare that I'm looking for e.g payload > doc id > content: "This is some content"?.
Here are some information that are helpful about how Firestore operates and they may prove helpful to you on how to improve queries in your database.
Here is the Firebase documentation about queries and the Query Client Library.
This is an article that refers to the causes of slow queries.
Regarding your second question you can get a snapshot of the whole document and then you have to iterate through the data.
Let me know if this is helpful to you.