How to read last message node in firebase for js app? - javascript

I want to read last message node as shown in image below.
I am using below query to retrieve last message where suid and ids are known(as shown in img). but not working.
firebase.database().ref("Messages/"+suid).child(ids+"/chat").orderByKey().limitToLast(1);
How to retrieve last message from firebase realtime db and display it to my console? Thanks

Your existing code looks fine, so let's store that query in a variable first:
const query = firebase.database().ref("Messages/"+suid).child(ids+"/chat").orderByKey().limitToLast(1);
Now you can read the message(s) this query matches with either once() or get(). I'll use once(), since it's much older and hence you're more likely to find examples of it elsewhere:
query.once("value").then((snapshot) => {
snapshot.forEach((message) => {
console.log(message.val().message.msg);
});
})
Some things to note here:
Since a query may have multiple results, the snapshot contains a list of those results. Even if there's only a single result (like here), the snapshot is a list of one result. To loop over these results, we use snapshot.forEach().
Your msg is nested under message in each child, so we use message.val().message.msg to get at its value.

Related

Unable to get document data in firestore

I'm trying to access data from a firestore document, but I'm getting an error message that exercise.data() is not a function. I don't understand how the exercisesToAdd array is an array of documents, but I can't use .data() to get the contents of the items? How else would I go about getting the data from those documents?
I know the exercisesToAdd array is actually being filled with documents because I see them in the database when I send the array. Seems straight-forward but I must be missing something.
chosenExercises.forEach((exercise) => {
exercisesToAdd.push(doc(db, 'Users/' + auth.currentUser.uid + '/Exercises/' + exercise));
});
exercisesToAdd.forEach((exercise) => {
console.log(exercise.data());
});
As #Doug Stevenson stated in his comment:
Your code hasn't actually performed any queries, so there is no document data available. Please review the documentation and use get() to execute each document query first before calling data() on anything. All doc() does is create a DocumentReference, which doesn't contain any data.

Reducing the amount of reads in a where query

I have recently implemented firebase into my project and I have created a user collection, this collection has a document for each user and each document has about 8 fields, when my user launches the app, I am trying to pull the document that corresponds to his data, so im doing the following query:
async function getUserData() {
const _collection = collection(db, "users")
const _query = query(_collection, where("userid", "==", uniqueUserID))
const querySnapshot = await getDocs(_query)
querySnapshot.forEach((doc) => {
console.log(doc.data())
})
setLoadingStatus(false)
}
This query works and gives me the corresponding user data, but the problem is, if the user is too far down the collection, this will execute 8 reads per document until it gets to the corresponding user, I have tried to implement a cache system using a lastModified but I still need to read the document data for that field and it will end up using more or less the same amount of reads. My question is: How do I reduce the amount of read operations that get executed when im trying to compare values in the documents, I have also thought of adding an a like so a_uniqueUserID so it gets ordered alphabetically and takes the first spot of the document but it's hacky.
EDIT: Here is what my structure looks like:
I think you are misunderstanding the definition of a document and a field. When you read a document, you always get all fields out of it. The snapshot contains everything read, even if you don't use it. There is no additional cost per field, other than the storage required to hold it all. In your screenshot, you show 5 documents, and one of those documents have 8 fields.
You are probably misunderstanding the metrics in the console. When you read and write documents using the console, those are also billed as reads and writes - use of the console is not "free". What you are seeing is a combination of what your app is doing in combination with what you're doing in the console.

get more data after some given id in firebase

I'm new using firebase and I'd like to make an infinite scroll pagination to my posts.
Suppose I have this post IDS:
-M5HMGs3EnBv6O2NSxG
-M5HMGsA3YyW_NJ3fSV
-M5HMGsdfLOOEPPBR_s
-M5HMGsiH9HIZw9DNaz
-M5HMHFYoUX8kNolLrP
-M5HMHFZvDrV27S2hSt
-M5HMHFnrQ_l4mVQ0rX
-M5HMHFoaV8wbexwPCd
-M5HMJQaaFGxF450lJB
-M5HMJQe319R19Cvak6 // THE LAST ONE IN FIRST PAGINATION
-M5HMJQh2gWuah7GSht
-M5HMJQlrcfTTF3fbbI
-M5HMJQo6QT1HwWP2lz
-M5HMJQrIUiZyzhiqK3
-M5HMJQudSkFdvs42D1
-M5HMJRCmbFbxKp1NgA
-M5HMJRFwfo7yN8Is3-
-M5HMJRIsKT3YmoukQ0
-M5HMJRKDTq7XuqtshT
-M5HMJRNRabXbYQUMi6
-M5HMJRS1t9UBzH_3Jh
-M5HMJRXEv6BaPeQPMn
-M5HMJR_bRdxCBy-uma
-M5HMJRdOPBA-SMoMjB
So, first I get the first 10 posts till the id M5HMJQe319R19Cvak6 using this:
var starCountRef = firebase.database().ref('/posts/').limitToFirst(11);
it is ok. When I go to the last post my reactjs will call this function again sending the last loaded post ID (the M5HMJQe319R19Cvak6) in variable pageNumber.
What I'd like to do is get posts after this last id given to continue the pagination, like so:
-M5HMJQh2gWuah7GSht
-M5HMJQlrcfTTF3fbbI
-M5HMJQo6QT1HwWP2lz
-M5HMJQrIUiZyzhiqK3
-M5HMJQudSkFdvs42D1
...
I tried to use startAt(ID) but no result has shown:
var starCountRef = firebase.database().ref('/posts/').limitToFirst(11).startAt(pageNumber);
any ideas how can I get posts after an id in firebase?
Firebase Realtime Database queries consists of two steps:
You call one of the orderBy methods to order the child nodes on a specific value.
You then call one of the filtering methods (startAt, endAt, equalTo) to determine where to start and stop returning data.
Your code does that second step, but fails to do the first step. This means that you're using Firebase's default sort-order, which is by each node's priority. Priorities are a left-over from the days then this API didn't have any better sorting options. These days, you'll always want to call orderBy... before filtering.
With that knowledge, your query for getting the second page of results should look something like:
firebase.database()
.ref('/posts/')
.orderByKey()
.startAt("-M5HMJQe319R19Cvak6")
.limitToFirst(11)
I highly recommend calling the "-M5HMJQe319R19Cvak6" value something else than pagenumber as that variable name makes it seem as if Firebase queries are offset-based, which they aren't.

Firebase Search and Update By Child's Child

I have following structure of firebase database:
-files
|-LJsSTIfXcyzZy9N8RDV
|-fileURL:"uploads/myfile.png"
|-LJsSTIfXcyzxy9N8PqT
|-fileURL:"uploads/myfile2.png"
Now i want to add a sibling of fileURL by using only value of fileURL.
So using value 'uploads/myfile.png' i am trying to acheieve following:
-files
|-LJsSTIfXcyzZy9N8RDV
|-fileURL:"uploads/myfile.png"
|-fileThumbURL:"uploads/myfileThumb.png"
|-LJsSTIfXcyzxy9N8PqT
|-fileURL:"uploads/myfile2.png"
I have tried following but it doesn't work.
fileURL = "uploads/myfile.png";
thumbURL = "uploads/myfileThumb.png";
admin.database().ref().child('files').orderByChild("fileURL").equalTo(fileURL ).once('value',function(snapshot){
return snapshot.ref.child('fileThumbURL').set(thumbURL);
});
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 needs to handle this list, typically by using snapshot.forEach() to loop over the results. For example:
admin.database().ref().child('files').orderByChild("fileURL").equalTo(fileURL ).once('value',function(snapshot){
snapshot.forEach(function(fileSnapshot) {
fileSnapshot.child('fileThumbURL').set(thumbURL);
});
});

How to loop through messages and delete certain ones in firebase?

I am using firebase and want to loop through my messages that I have and delete certain ones based upon a user's uid.
Here is an image of what I have for the structure of my data:
So far I know you would start of as something like:
Firebase.database().ref('messages').on('value', snapshot => {
snapshot.forEach(snap => {
if(snap.val().user.id === currentUser.uid){
//delete message here
};
});
});
Where do I go from here?
First of all, you probably want to use once() instead of on(). If you modify the contents of the database that you're working with, your on() will get triggered again for each change. You can see how that might be problematic for your case, if you only want to loop through the data once. Definitely learn about the difference between once() and on().
If you have a DataSnapshot type object, you can delete the contents of the database at its location with
snap.ref.remove()
Definitely read up on the Reference object type.

Categories