How to sort Firebase real-time database by the child node with the highest number of

I am working on a database feature that allows users to 'like' comments on posts.

Is there a way for me to sort the comments based on the number of likes they have?

Although I am aware of using .orderByChild(), my issue lies in not having a separate child for the 'like' count.

Currently, I store user UIDs and timestamps within the original commentID child to handle likes.

Would it be feasible to retrieve comments based on the child with the highest number of sub-children?

The structure of my database is as follows:

{
 "users" : {
  "$uid" : {
   "posts" : {
    "$postID" : {
     "postText" : "blah blah blah",
      "comments" : {
       "$commentID" : {
        "commentText" : "blah blah blah",
         "likes" : {
          "UID01" : "1622035190516",
          "UID02" : "1622036141955",
          "UID03" : "1622036145134",
         }
       },
       "$commentID" : {
        "commentText" : "blah 2 blah 2 blah 2",
         "likes" : {
          "UID01" : "1622036141955",
          "UID02" : "1622036145134",
         }
       }
      }
    }
   }
  }
 }
}

Answer №1

Is there a way to retrieve comments based on the child with the highest number of children?

Unfortunately, it is not possible to sort data based on dynamic aggregations.

In the realm of NoSQL databases, a common solution is to maintain a counter. A recommended approach is using a Cloud Function, such as Firebase's Cloud Functions, for backend calculations done via Admin SDK. This allows you to secure the database nodes containing the like counts with appropriate security rules to prevent unauthorized modifications.


Specifically, you should:

1/ Initialize the counter to 1 when the first like is recorded. The following onCreate Cloud Function can be used for this purpose:

exports.initializeCounter = functions.database.ref('users/{uid}/posts/{postID}/comments/{commentID}/likes')
    .onCreate((snapshot, context) => {
      return snapshot.ref.parent.child('nbrOfLikes').set(1);
    });

2/ Update the counter whenever a like is added or removed using an onUpdate Cloud Function that calculates the total likes and updates the counter accordingly. The below Cloud Function demonstrates this process:

exports.updateCounter = functions.database.ref('users/{uid}/posts/{postID}/comments/{commentID}/likes')
    .onUpdate((change, context) => {
        const likeObject = change.after.val();
        return change.after.ref.parent.child('nbrOfLikes').set(Object.keys(likeObject).length);
    });

An alternative method would be utilizing the numChildren() method, as discussed in this answer.


Keep in mind the scenario where all likes are deleted, if applicable in your application.


It is worth noting that the two (or three) Cloud Functions can possibly be consolidated into a single onWrite Cloud Function.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The redirect feature in getServerSideProps may not function properly across all pages

Whenever a user visits any page without a token, I want them to be redirected to the /login page. In my _app.js file, I included the following code: export const getServerSideProps = async () => { return { props: {}, redirect: { des ...

Adding to the beginning of a list in JQuery mobile

Having trouble figuring out how to prepend my list in jQuery mobile while keeping the divider on top of the most recent item added. I attempted to prepend the newly added item, but it ended up shifting the divider to the bottom instead. function loadScan ...

What distinguishes running rm -rf node_modules + npm i from using npm ci?

When using a Unix system and needing to clean out the node modules folder, is there any benefit or distinction between executing rm -rf node_modules followed by npm i as opposed to npm ci My understanding is that both yield the same outcome, but is th ...

Can webpack integrate React components from a package and then recompile the package?

I am currently in the process of creating an npm package to standardize my layout components that are based on geist components. Initially, I attempted to use the npm package as a local component, but encountered a webpack loader error when trying to read ...

Issues with the navigator.contacts.find function occurring when using cordova or phonegap

I am attempting to retrieve the contacts stored on a mobile device. The code snippet I am using is not functioning as expected - specifically, the navigator.contacts.find method isn't producing any outcomes. There are no error messages or success conf ...

Eliminate the array from the data retrieved through an http request in AngularJS

Currently, I am making an http call to retrieve data from a database. This process involves calling 6 different types individually. $scope.getAll = function() { var url = 'http://someurl/'; var allObjects = []; $sc ...

Tips for effectively utilizing innerHTML in this particular scenario

For an assignment, we were tasked with creating a Madlib game where users input words into textfields to replace certain words in a hidden paragraph within the HTML using JavaScript and CSS. The paragraph embedded in the HTML page is as follows: <span ...

AngularJS - Leveraging the power of two-way data binding with JSON strings

I am a beginner with AngularJS and I'm currently working on retrieving, parsing, and displaying data from a SOAP web service. So far, I have been able to successfully make calls to a public weather service, capture and display the XML data that is ret ...

I must add and display a tab for permissions

I am currently using the material UI tab for my project. My goal is to display the tab only when the permission is set to true. I have successfully achieved this functionality, but the issue arises when the permission is false. It results in an error that ...

employing flush for lodash's throttle wrapper

When using TypeScript with JavaScript and Angular: I am trying to use the throttle decorator from lodash to limit an API call while a user is navigating around the page, ensuring that it fires before they leave the site. In my TypeScript constructor, I h ...

Transitioning from SJAX to AJAX

I am in the process of updating a portion of my script to use AJAX instead of Synchronous JAX to prevent the page from freezing. My goal is to check if a password is valid before sending it to the server. If the password is not valid, I want the password f ...

Using JavaScript to choose an option within an optgroup

Is there a way to automatically select the option in the optgroup when I choose a user from the select list? Here is an example of the select code: <select name="city"> <optgroup label="Zone 1"> <option value=" ...

Encountering a 401 Error while trying to host an Angular app on Google Cloud Storage

I am currently facing an issue with deploying my Angular app to a Google Cloud Storage bucket. The bucket is public and set up to be served as a custom website via CNAME (test.example.com). The main page and 404 handler are mapped to index.html, but I am e ...

What could be causing JSON.parse to encounter errors when parsing a string array?

Within the following function, I am utilizing JSON.parse() on specific string arrays saved in window.sessionStorage. This allows me to apply methods like .map(). window.sessionStorage = { myArray1: "["805746|search|4","980093062|search|0","980113648| ...

There are a multitude of unfamiliar files within the node_modules directory

I've been following a tutorial by Kent C. Dodds on creating an open source library. In the process, I used npm to install various packages such as chai, commitizen, cz-conventional-changelog, mocha, and unique-random-array. Recently, I noticed that m ...

Verify if the element in the array is set to true

Using a simple boolean in a condition is straightforward : var running = true; if(running) {/*do something*/} But what about using a boolean array? Can it be done like this: var running = [false,false,true,false]; if(running[]){/*do something*/} Curren ...

Error with replacing regular expressions in IE11 for the variable $0

Having both a string and a message: str = "Test $0 $1 $2"; message = "Hi %2 Hello %2" ; The goal is to replace all occurrences of %2 with str in the message using RegExp, like so: message = message.replace(new RegExp("%2" , "g"), str); While this works ...

Issues with Angular JS page loading when utilizing session and local storage in Google Chrome

I'm currently learning about AngularJS and I stumbled upon this helpful tutorial http://embed.plnkr.co/dd8Nk9PDFotCQu4yrnDg/ for building a simple SPA page. Everything was working smoothly in Firefox and IE, except when it came to using Local and Sess ...

Sending Java Servlet JSON Array to HTML

I am currently engaged in a project that requires extracting data from a MySQL database and implementing pagination. My approach involves utilizing JSON AJAX and JavaScript, although I am fairly new to JSON and AJAX. After successfully retrieving the neces ...

Utilize moment.js to convert an epoch date into a designated time zone

I've spent countless hours searching for a resolution to the issue with moment.js and its inability to accurately display the correct date for a given local time zone. Let me explain my predicament: The flight API I'm utilizing provides me w ...