0

I'm new to using the firebase database with javascript, I tried sorting like this

db.ref (). Child ('Items'). OrderByChild ('upvotes')

But it doesn't work as it should.

I need to sort objects by the number of votes, the number of votes is now calculated as follows: upvotes.numChildren() - downvotes.numChildren()

I need to sort them in descending order

Please tell me how to sort by the number of childs of the element, or if it is impossible, some alternatives

Database example

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Michael2322
  • 13
  • 1
  • 3
  • You can't. You need to reverse the array using Javascript. You can check [this](https://stackoverflow.com/q/45357920/13130697) – Dharmaraj Apr 26 '21 at 13:10

2 Answers2

0

That's not possible directly in the Firebase query. You would have to fetch the data once which will be in ascending order, then reverse that and process it using Javascript yourself.

const db = firebase.database()
db.ref("posts").once("value").then((snapshot) => {
  const rawData = []
  snapshot.forEach((post) => {
    const postName = post.name
    const upvotes = Object.keys(post.upvotes).length
    const downvotes = Object.keys(post.downvotes).length
    rawData.push({name: postName, upvotes: upvotes, downvotes: downvotes, score: upvotes - downvotes })
  })
  console.log(rawData)
})

Now the only part left is you would have to sort this array based on the property score.

I have a few suggestions:

  1. This data structure is not ideal or economical. Firestore would have been a better choice both for structure and querying but this existing structure can be improved a bit.
  2. There is no property called ".size" as mentioned in your screenshot. You must store a count of upvotes and downvotes explicitly in their respective nodes. Then you would be able to use .orderByChild("upvotes.size") in the query.

Let me know if you need more clarification.

Dharmaraj
  • 47,845
  • 8
  • 52
  • 84
  • Thank you very much for your reply! I think your answer is correct. You said this data structure is not ideal or economical. If it's not difficult for you, can you advise me on how to better structure my data? – Michael2322 Apr 26 '21 at 20:52
0

You seem to be hitting all the sweet spots of things Firebase doesn't do. Luckily all of them have well documented workarounds, so let's go through them:

  1. There is no built-in count function. If you want the count of upvotes you'll either have to download all the upvotes, or store the upvoteCount in addition to the individual upvotes and update that each time a vote is cast. At scale, only that last option is realistic, so you end up with two additional properties: upvotesCount and downvoteCount.
  2. There is no way to query on a calculated value, like your downvoteCount - upvoteCount. If you want to order on something, that needs to be stored as a value in the database, so we end up with another additional property voteScore, which is upvoteCount - downvoteCount.
  3. Firebase always returns results in ascending order. If you need to display the items in descending order, you have two options: either reverse them client-side, or store an inverted value and sort on that. If you chose the latter, you end up with a fourth new property: sortCount = downvoteCount - upvoteCount.

For more on all of these also see:

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807