I wanted to fetch the fields inside the subcollection but it is returning "undefined" and the database is designed like this:
Collection
Document
Collection
Document
Field
here is the code:
const getEventInfo = async () => {
await firebase
.firestore()
.collection("events/" + eventId + "/agenda")
.doc(customerCollectionIds)
.get()
.then((doc) => {
console.log(doc.data())
})
.catch((error) => {
console.log("Awit Error getting document:", error)
})
}
I am using reactjs. what am I missing here?
Related
I'm trying to fetch muliple collection from firebase that starts with specific text, but i can't fetch them all, It just fetch only one collection
this a picture of firebase collections that i want to fetch starts with 'Buyer-Cart'
const Uid = auth.currentUser.uid;
useEffect(() => {
fs.collection("Buyer-Cart "+Uid)
.get()
.then((Snapshot) => {
const data = Snapshot.docs.map((doc) => {
return doc.data();
});
setOrderIds(data);
});
}, []);
I am trying to delete a firebase document but the problem is I want to delete specific documents using fields.
as seen above I have user_uid_1 and user_uid_2 in many documents. and I want to match them like every document with (401 and 337) should be deleted when I click delete.
export const deleteChat = (chatId) => {
return async (dispatch) => {
const db = firestore();
db.collection("conversations")
.doc(chatId)
.delete()
.then(() => {
dispatch({
type: userConstants.GET_REALTIME_MESSAGES,
});
})
.catch((error) => {
console.log(error);
});
};
};
You could query using the where method and loop the delete() method for each document found. See sample code below:
const coversations = db.collection('conversations')
.where('user_id_1', '==', '401')
.where('user_id_2', '==', '337');
coversations.get().then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
doc.ref.delete();
});
});
If (401 and 337) can be in both user_id_1 and user_id_2, you can do a simple logic to check if there's an occurrence on the field. See sample code below:
const coversations = db.collection('conversations');
coversations.get().then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
const n = ['401', '307'];
if (n.includes(doc.data().user_uid_1) && n.includes(doc.data().user_uid_2)) {
doc.ref.delete();
}
});
});
I'm trying to build compound query in Expo react native - firestore.
I have 2 collections in firebase. First "node" is userID and second are IDs of places that had been discovered by this user. Then, I need to take this array of place IDs and pass it as parameter in 2nd query where I got name of each place stored in collection named "databaseOfPlaces". (I want to make scrollable view with names, so maybe I should add listener later on?)
My solution is not working very well. Can you help me? Is this the right way, or is there another way how to save DB call?
Thank you very much.
This is my code:
async componentDidMount() {
db.collection("placesExploredByUsers") // default
.doc("mUJYkbcbK6OPrlNuEPzK") // default
.collection(auth.currentUser.uid)
.get()
.then((snapshot) => {
if (snapshot.empty) {
alert("No matching documents.");
return;
}
const users = [];
snapshot.forEach((doc) => {
const data = doc.data();
users.push(data);
});
this.setState({ users: users });
})
.catch((error) => alert(error));
db.collection("databaseOfPlaces")
.where('placeID','in',this.state.users)
.get()
.then((snapshot) => {
if (snapshot.empty) {
alert("No matching documents.");
return;
}
const places = [];
snapshot.forEach((doc) => {
const data = doc.data();
places.push(data);
});
this.setState({ places: places });
})
.catch((error) => alert(error));
}
Data is loaded from Firestore (and most modern cloud APIs) asynchronously. By the time your second query now runs, the results for the first query are not available yet.
Because of this, any code that needs the results from the first query, will need to be inside the then() callback of that query.
So:
async componentDidMount() {
db.collection("placesExploredByUsers") // default
.doc("mUJYkbcbK6OPrlNuEPzK") // default
.collection(auth.currentUser.uid)
.get()
.then((snapshot) => {
if (snapshot.empty) {
alert("No matching documents.");
return;
}
const users = [];
snapshot.forEach((doc) => {
const data = doc.data();
users.push(data);
});
this.setState({ users: users });
db.collection("databaseOfPlaces")
.where('placeID','in', users)
.get()
.then((snapshot) => {
if (snapshot.empty) {
alert("No matching documents.");
return;
}
const places = [];
snapshot.forEach((doc) => {
const data = doc.data();
places.push(data);
});
this.setState({ places: places });
})
})
.catch((error) => alert(error));
}
How do I go about setting a specific firestore document field to state.When ever i try to run this i get the following warning.
(Im trying to get an array from firestore if that helps)
Possible Unhndled Promis Rejection (id: 0): TypeError: doc.data is not a function. (In 'doc.data()', 'doc.data' is undefined)
class Chart extends React.Component {
constructor(props) {
super(props);
this.state = {
data: []
};
}
componentDidMount() {
db.collection("users")
.where("email", "==", firebase.auth().currentUser.email)
.get()
.then(doc => {
this.setState({ data: doc.data().prevlevel });
});
}
render(){
const data = this.state.data
.....
You're firing a query against a collection. A query can have multiple results, and thus returns a QuerySnapshot and not a document. Even when there is only one document matching your criteria, it'll still be in a QuerySnapshot.
So your callback will have to iterate over the results. If you only expect one result, you could do that with:
db.collection("users")
.where("email", "==", firebase.auth().currentUser.email)
.get()
.then(querySnapshot => {
querySnapshot.forEach(doc => {
this.setState({ data: doc.data().prevlevel });
})
});
You are currently getting a collection, not a document. If you want to get a doc, you'll need to add that to your request, as in:
db.collection("users")
.where("email", "==", firebase.auth().currentUser.email)
.doc('someId') // <-- Added this, but i don't know exactly what id you need
.then(doc => {
this.setState({ data: doc.data().prevlevel });
});
Or if you do want a collection, then you'll need to use the properties found on collections, as in:
.then(snapshot => {
this.setState({ data: snapshot.docs });
})
Firebase Firestore Guides show how to iterate documents in a collection snapshot with forEach:
db.collection("cities").get().then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
console.log(doc.id, " => ", doc.data());
});
});
I imagined it would support map as well, but it doesn't. How can I map the snapshot?
The answer is:
querySnapshot.docs.map(function(doc) {
# do something
})
The Reference page for Firestore reveals the docs property on the snapshot.
docs non-null Array of non-null firebase.firestore.DocumentSnapshot
An array of all the documents in the QuerySnapshot.
Got pretty sick and tired of Firestore returning stuff in their classes or whatever. Here's a helper that if you give it a db and collection it will return all the records in that collection as a promise that resolves an actual array.
const docsArr = (db, collection) => {
return db
.collection(collection)
.get()
.then(snapshot => snapshot.docs.map(x => x.data()))
}
;(async () => {
const arr = await docsArr(myDb, myCollection)
console.log(arr)
})()
// https://firebase.google.com/docs/firestore/query-data/get-data
const querySnapshot = await db.collection("students").get();
// https://firebase.google.com/docs/reference/js/firebase.firestore.QuerySnapshot?authuser=0#docs
querySnapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() }));
Here's another example
var favEventIds = ["abc", "123"];
const modifiedEvents = eventListSnapshot.docs.map(function (doc) {
const eventData = doc.data()
eventData.id = doc.id
eventData.is_favorite = favEventIds.includes(doc.id)
return eventData
})
I have found that a better way to do this by using map and get your document id as well is as follows:
start with the object array I wish to update in your constructor:
this.state = {
allmystuffData: [
{id: null,LO_Name: "name", LO_Birthday: {seconds: 0, nanoseconds: 0},
LO_Gender: "Gender", LO_Avatar: "https://someimage", LO_Type: "xxxxx"},],
};
and in my function do the following
const profile = firebase
.firestore()
.collection("users")
.doc(user.uid)
.collection("stuff")
.get()
.then( async (querySnapshot) => {
console.log("number of stuff records for ",user.uid," record count is: ",
querySnapshot.size);
const profile = await Promise.all(querySnapshot.docs.map( async (doc) => {
const stuffData = doc.data()
stuffData.id = doc.id
condole.log("doc.id => ",doc.id)
return stuffData
}));
this.setState({allmystuffData: profile});
})
.catch(function (error) {
console.log("error getting stuff: ", error);
})
In this example I read all the documents in the collection with querysnapshot the when mapping accross them. the promise.all ensures that all the records are returned before you render it to your screen. I add the document id to the "id" element of each object in the array returned, then I use setstate to replace my state array with the array returned from the query.
you can try this
FirebaseFirestore.instance
.collection('Video_Requests')
.get()
.then((QuerySnapshot querySnapshot){querySnapshot.docs.forEach((doc){
print(doc.data());
});
});