I'm beginner to firestore.
My query always give the same data independently of the value i pass into startAfter() function.
here's code:
const fetchMore = async () => {
const q = query(
collection(db, 'chat-messages'),
orderBy('createdAt', 'asc'),
startAfter(23),
limit(5),
);
const querySnapshot = await getDocs(q)
querySnapshot.forEach(doc => {
console.log(doc.data())
})
}
Thanks for reading and helping!
Have a nice day
here's the console.log
I'm not sure what type the data in your startAt field is, but I guess it's a date or a Firestore Timestamp.
Pagination in Firestore is not based on numeric offsets, as you may be used to from other databases, but instead is based on so-called cursor objects: knowing the values and/or ID of the document you want to start after.
So you'll need to pass in the timestamp that you want to start after, not the number of documents you want to skip. So for example, to get all documents with a createdAt after now, you could do:
startAfter(Timestamp.now())
For more on this way of pagination, see the documentation on paginating data with query cursors.
Related
I fetch data from my firestore database like thus:
const [songs, setSongs] = useState();
async function getSongs() {
const songs = collection(db, 'songs');
const songSnapshot = await getDocs(songs);
const songList = songSnapshot.docs.map(doc => doc.data());
setSongs(songList);
console.log(songList);
console.log(songs);
};
If I run this, there are two objects in the console, the first one is songList, and the second one is songs:
Why is there a difference between the two? What do I do to turn songs back into an array?
"songs" is a CollectionReference and does not contain the data. "songList" is an array which contains data from the documents returned by getDocs(). You should set songList in your state instead of songs
From the documentation,
A CollectionReference object can be used for adding documents, getting document references, and querying for documents (using query()).
I'm using vue3 and firestore
Referring to the firestore official document, there was a way to get documents through collection. But this is the way to get all the collection data.
const citiesRef = db.collection('cities');
const snapshot = await citiesRef.get();
snapshot.forEach(doc => {
console.log(doc.id, '=>', doc.data());
});
I want to get a single document through collection.
How to get a single documemt is
const cityRef = db.collection('cities').doc('SF');
const doc = await cityRef.get();
This is a collection followed by a doc().
I can't insert a value in the doc because documemt is an auto-generated ID.
So I don't know what to do.
You have not mentioned the which document you are specifically looking for. In case you don't know the ID of the Firestore Document, you can try running a simple query using .where() like this:
const db = firebase.firestore()
db.collection("cities").where("cityName", "==", 'London').get().then(querySnapshot => {
const matchedDoc = querySnapshot.doc[0]
})
The example above finds the document where the field cityName is equal to London (both case sensitive). QuerySnapshot contains all the documents which matched your condition specified in the where() method. But in case you know there is only one matching document, as in my case I only have one doc with cityName as London, you can directly access the doc data this way: querySnashots.docs[0].data(). querySnapshot.docs is an array. [0] is the first document in it and .data() parses data from the doc. Additionally you can use querySnapshot.size to get count of documents returned from the query.
I want to clean some records of a firestore database. I have a function that receives the records I would like to keep, I check in all the records if id is not in the docsToKeep:firebase documents argument.
I use a foreach for all the records, and I user filter to find the matching id as shown in the working snippet below:
async function checkForNotifClean(docsToKeep:firebase.firestore.QuerySnapshot<firebase.firestore.DocumentData>) {
const db = firebase.firestore();
const notifCollection = db.collection('notifications')
const allData = await notifCollection.get();
allData.docs.forEach(doc => {
const filtered = docsToKeep.docs.filter(entry => entry.id === doc.id);
const needsErase = filtered.length === 0;
if (needsErase) {
const id = doc.id;
notifCollection.doc(id).delete();
}
})
}
Is there a cleaner way to erase all the documents that are not in docsToKeep ? Would be kind of function that get all the objects that are not in both arrays and delete those. I would be happy on improvements on the javascript side to filter out the records to delete, and in the firebase side, improvements regarding the chance of deleting some set of records at once instead of looping through all and deleting each.
To delete (or write to) a document in Firestore you need to know the complete path to that document, including its document ID. If you don't have the IDs of the documents to delete, then your only option is to determine those IDs as you're doing now.
It does lead to the question how docsToKeep is populated though. My guess it that the user already selects some documents from a full list. If that's the case, might you be able to pass the inverted list: docsToDelete?
I am currently working on a mobile app on React and I am having trouble understanding how to save a field from fire store that is an array.
Since I can't post images my database structure is all strings such as username, first name, etc but I have a field called follow list that is an array.
What I want to do is save the usernames from the following list into an array to later search fire store for the username's in the array, this is basically what I want to do so I can render my app's social Feed. I do know that I can probably create another subcollection and write something familiar to what I did to search for users but that was a QuerySnapShot which was overall documents not a specific one and I also know firebase creates an ID for arrays and it increases as the array gets bigger.
I do not want to end up making two more subcollections one for followers and following which I think not ideal right? My current approach is this
export const fetchUserFollowing = async (username) => {
const ref = firebase.firestore().collection('users').doc(username)
let results = []
ref
.get()
.then( doc => {
let data = doc.data()
results = data
})
.catch((err) => {
return 'an error has occurred ', err
})
}
From what I understand is that a DocumentSnapShot .get() function returns an object but what I want is to store follow list into results and then return that but I am not sure how to manipulate the object return to just give me follow List which is an array
https://rnfirebase.io/docs/v5.x.x/firestore/reference/DocumentSnapshot
link to docs
I have this data
I do this query
firebase.database().ref(${path}/buy)
.orderByChild('price').limitToFirst(1)
.once('value')
.then(snapshot => console.log(snapshot.val()))
And I get this result
Then the question is
Is there an easy way to access the price attribute of the one object whose key I don't know?
e.g. snapshot.first().price or snapshot.only().price
Simply put, I want to avoid this
var result = snapshot.val()
var key = Object.keys(result)[0]
var price = result[key].price
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.
In your callback you need to handle this list by using snapshot.forEach():
firebase.database().ref(${path}/buy)
.orderByChild('price').limitToFirst(1)
.once('value')
.then(snapshot => {
snapshot.forEach(function(child) {
console.log(child.val());
console.log(child.val().price);
})
})