A firestore query not working in react-native - javascript

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.

Related

need help accessing Firestore sub-collection?

I'm a novice when it comes to coding (started teaching myself ~year ago), any help will be much appreciated, thank you in advance.
I saw that there is 3-4 other post on stack overflow on how to access Firestore's sub-collections.
I tried them all and had no luck, hence why I'm posting this as a new question.
right now I have my data set is up as: collection/document.array. And that was fine till now because I just needed to read that data from the array to draw it out in my little React project with .reduce and .map and push new data to that array on input.
this is the code I have right now for getting data from Firestore:
--- in firebase.js ----------------------------------------------------------------------
export const fire = firebase.initializeApp(config);
export const db = fire.firestore()
_________________________________________________________________________________________
--- in events-context.js ----------------------------------------------------------------
const fetchEvents = async () => {
try {
const data = await db.collection('events').get();
setEvents(data.docs.map(doc => ({ ...doc.data(), id: doc.id })));
} catch ({ message }) {
alert(`Error # fetchEvents, Error:${message}`);
}
};
But now I want to add edit and a remove feature, but in order to do that, I need to carry out my array of data into a sub-collection so each individual element from that array had its own id so that I could later target it. so it needs to be set up something like this: collection/document/sub-collection
To access a document inside a collection, you must know the document ID from another source. This can be done by managing the names inside an array of strings or maps that you can then process within your app per your design.
For example: once created, you will have a snapshot of the reference of which you can store the document id inside the parent document:
db.collection("events").doc(id).update({
payers: firebase.firestore.FieldValue.arrayUnion(paySnapshot.ref.id)
})`
Once you have this information, you can append it to the relevant document path using one of the following techniques.
db.collection("events").doc(id).collection("payers").doc(pay_id).get()
db.doc(\events/${id}/payers/${pay_id}`).get()`
I strongly advise against using .get() on a collection without limit() and where() conditions to reduce the reads that can occur.
Try this, it works for me :)
Insert data >>>
const q = query(collection(this.fire, "events"));
const querySnapshot = await getDocs(q);
const queryData = querySnapshot.docs.map((details) => ({
...details.data(),
id: details.id,
}));
console.log(queryData);
queryData.map(async (v, id) => {
await setDoc(doc(this.fire, `events/${auth}/more`, events.title), {
'title': events.title,
'uid': auth,
//your data here
})
})
Read Data >>>
const querySnapshot = await getDocs(collection(this.fire,
`/events/${auth}/more/`)); querySnapshot.forEach((doc) => { //
doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data()); });
return querySnapshot;

Delete document in firestore when value of document matches

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)

How to get out a certain field value from a object from a array in Javascript

I'm learning firebase cloud functions with JavaScript,
I get a QuerySnapshot back of a collection of documents each document holds an ID field and a message field.
Where I'm stuck now is that every time I loop through the collection I want to be able to just take the ID field out from each object and save it.
I've tried all the ways that I can think of that come up on Google and stack overflow none are working for me, I'm obviously doing something wrong.
I'm totally new to JavaScript so this may be an easy fix if anyone has any information
This is my code in visual studio that I'm using, which is working fine from where I can see to get to the collection that I need to
// onDelete is my trigger which would then go and fetch the collection that I want
exports.onDelet = functions.firestore.document('recentMsg/currentuid/touid/{documentId}').onDelete(async(snap, context) => {
const data = snap.data();
const contex = context.params;
// once I get the information from onDelete the following code starts
await admin.firestore().collection(`messages/currentuid/${contex.documentId}`)
.get()
.then((snapshot) => {
//this array will hold all documents from the collection
const results = []
const data = snapshot.docs.map((doc) => ({
id: doc.id,
...doc.data(),
}));
results.push(data)
console.log(results)
//This is one of the ways I've tried
//results.forEach((doc) => {
//console.log(doc.id)
//this is a print out in the terminal
// > undefined
// } );
});
Below is a print out that I get in terminal which is all the information that it holds which is great,
But really all I want is to have an array that holds every id
if there was just one value in the array I know this would not be a problem but because there is an object with multiple values that's the issue.
i functions: Beginning execution of "onDelet"
> [
> [
> { id: '28ZyROMQkzEBBDwTm6yV', msg: 'sam 2' },
> { id: 'ixqgYqmwlZJfb5D9h8WV', msg: 'sam 3' },
> { id: 'lLyNDLLIHKc8hCnV0Cgc', msg: 'sam 1' }
> ]
> ]
i functions: Finished "onDelet" in ~1s
once again apologies if this is a dumb question I'm a newbie.
With await admin.firestore().collection(messages/currentuid/${contex.documentId}) .get() you get a QuerySnapshot that supports forEach and not map. Just write your code like this:
// onDelete is my trigger which would then go and fetch the collection that I want
exports.onDelet = functions.firestore.document('recentMsg/currentuid/touid/{documentId}').onDelete(async(snap, context) => {
const data = snap.data();
const contex = context.params;
// once I get the information from onDelete the following code starts
await admin.firestore().collection(`messages/currentuid/${contex.documentId}`)
.get()
.then((snapshot) => {
//this array will hold all documents from the collection
const results = []
snapshot.forEach((doc) =>{
results.push({id:doc.id,...doc.data()})
});
console.log(results)
//This is one of the ways I've tried
//results.forEach((doc) => {
//console.log(doc.id)
//this is a print out in the terminal
// > undefined
// } );
});
I assume that messages/currentuid/${contex.documentId} is a collecion and not a single document.
You can read more baout it here.

Cloud firestore not ordering problems when query

My query it's not ordering. Actually it doesn't response. I receive an empty results screen when trying with this:
let stateQuery = firestore.collection('categories').where('user', '==', uid).orderBy('name');
stateQuery.onSnapshot((querySnapshot) => {
const docs = [];
querySnapshot.forEach((doc) => {
docs.push({ ...doc.data(), id: doc.id });
});
setCategories(docs);
});
};
I tried also to do this, and nothing:
let stateQuery = firestore.collection('categories').where('user', '==', uid);
let stateQuery2 = stateQuery.orderBy('name');
The issue is that your query requires a Composite index. Documentation on composite indexes is on this page.
Check the console for an error message which should include the link necessary to create the composite index. When I run a similar query on my database, I get this link
https://console.firebase.google.com/v1/r/project/(PROJECTNAME)/firestore/indexes?create_composite=Xd1.....XTY

Receiving undefined when retrieving value from firebase

Where is my call wrong? The first console.log leads to the role object and the second console.log leads to undefined. When it should be the user.
componentDidMount(){
let user = fire.auth().currentUser;
let db = fire.database();
let roleRef = db.ref('/roles');
roleRef.orderByChild('user').equalTo(user.uid).once('value', (snapshot) => {
console.log(snapshot.val())
console.log(snapshot.val().user);
})
}
Result:
Firebase:
When you execute a query against the Firebase Database, there will potentially be multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result.
Your code doesn't take the list into account. The easiest way to do so is with Snapshot.forEach():
roleRef.orderByChild('user').equalTo(user.uid).once('value', (snapshot) => {
snapshof.forEach((roleSnapshot) => {
console.log(roleSnapshot.val())
console.log(roleSnapshot.val().user);
});
})

Categories

Resources