I am trying to sort entries in my firebase by the most recent entry showing up as the first entry. I keep running into the issue that the most recent entry shows up last.
I am trying to sort by time as well as this is how it is set up in my databases:
I am also doing this in my code
completed.child(user.uid).orderByValue("time")
I was wondering where I was going wrong
This is how it shows up in my app:
There are quite a few problems with your code, so I'll try to address them in turn.
To order by a child property, use orderByChild
You're calling orderByValue("time"), but if you check the documentation you'll note that orderByValue() takes no parameters. If you want to order on the value of a child property, you should call orderByChild("time").
Use a time format that allows sorting them
Your current time format is not suited for sorting it. The problem is that your lexicographical sort order doesn't match with the chronological sort order you want. More simply put, this is the sort order you'll get (but not want):
"6:26AM"
"6:26PM"
"6:27AM"
To get the result you want, use a string format that allows the sorting. For example, use 24 hour/military notation with 0-padding:
"06:26"
"06:27"
"18:26"
You could also store a numerical value, for example: the number of minutes since midnight:
(( 6 * 60) + 26) = 386
(( 6 * 60) + 27) = 387
((18 * 60) + 26) = 1106
Firebase always returns in ascending order
Firebase always returns results in ascending order. I'll recommend reading a few relevant questions, but you have two options here:
Reverse the results client-side. This is often the simplest, as you're usually dealing with relatively a small result set.
Store an inverted value in the database for sorting.
This last one is typically easiest if you use a numerical value, like the number of minutes since midnight that we used above. If we store -1 * this value, we can then sort on that to get the results in reverse.
-1 * (( 6 * 60) + 26) = -386
-1 * (( 6 * 60) + 27) = -387
-1 * ((18 * 60) + 26) = -1106
Related
I'm using localstorage to track domain visits and their timestamp.
Here's how I'm setting it:
localStorage.setItem(`${domain[0]}`, JSON.stringify(Date.now()));
What code would I use to delete all rows with a timestamp that's older than 30 days so users don't end up with too much extra data that probably won't be used?
I've seen a lot of examples about deleting individual rows based on the key. But I can't find anything related to bulk deleting based upon the values.
Enumerate all key/value pairs explicitly:
const cutOff = Date.now() - 30 * 24 * 3600 * 1000;
Object.entries(localStorage).forEach(([k, v]) => {
const time = JSON.parse(v);
if (time < cutOff) {
delete localStorage[k];
}
});
I need to get unique random number in javascript (or Typescript).
At this moment I use this code:
var id = -((new Date()).getTime() & 0xffff);
It returns me numbers like -13915 or -28806 ...
It works most of the time but I am having problems when this code is executed in promises (so nearly multiple times at the same time). Then sometimes I got two identical id.
Is there any solution to get unique random numbers in any case ?
There are many examples around internet. You can start with using Math.random()
. For example: generate random number between 1 and 100
Math.floor((Math.random() * 100) + 1);
Just keep in mind that it is not truly random; it is not cryptographically secure. You should probably look into libraries if you need that
Create a function that returns a unique number:
let numbers = [];
const uniqueNumber = (maxVal) => {
const number = Math.floor((Math.random() * maxVal) + 1);
if (!numbers.includes(number)) {
numbers.push(number);
return number;
} else if (numbers.length - 1 !== maxVal) {
uniqueNumber(maxVal);
}
}
const randomNumber = uniqueNumber(100);
console.log(numbers) // returns all unique numbers
This will return a unqiue number between 1 and 100. It also stops at the max length.
You can use the package uuid:
const uuidv4 = require('uuid/v4');
uuidv4(); // ⇨ '10ba038e-48da-487b-96e8-8d3b99b6d18a'
Notice: It is a number (a 128-bit number) but it is too big to be used as a JavaScript number. You have to keep it as a string.
If you need it on the browser, I suggest to generate the identifier from an API exposed on your back-end. Implementations of UUID exist in most of languages. The npm package will work on browsers but then it uses a fallback to Math.random, which is not secure.
See also: Universally unique identifier.
var datetimestamp = Date.now() + Math.random().toString(36).substr(2, 9);
Math.random() in itself should be safe enough, what with 64-bit numbers. Even with imperfect generator, the chances of hitting the same number twice are minuscule.
If you're after specifically integers, then multiply Math.random() by something BIG, like Number.MAX_SAFE_INTEGER.
To be perfectly safe, you can always store an array of already used ids, and write a function that draws as long as gets a new unique number, pushes it into array, and returns the value. Enclose all that functionality inside a single object/function/class, to keep it neat.
I have a database and I want to sort all posts by their score (an integer), I thought it would be super easy because I'm currently doing orderByChild('created') and it works perfectly, but for some reason orderByChild('score') doesn't work.
Here is my database structure:
score is an integer that can be negative, positive or 0.
The JavaScript I'm using:
this.subscription = this.database.database.ref('/posts/'+this.userData.location)
.orderByChild('score')
.startAt(new Date().getTime() - (24 * 3600 * 1000)) //last 24 hrs
.limitToFirst(10);
this.subscription.on('child_added', (snapshot) => {
this.postFeed.push(snapshot.val())
console.log(this.postFeed)
});
The weird thing is, the console.log isn't even firing so it's not even getting to that stage for some reason, but if I change .orderByChild('score') to .orderByChild('created') it works exactly as expected...
Any ideas what I'm doing wrong? Thank you!
I believe it might be something to do with this line
.startAt(new Date().getTime() - (24 * 3600 * 1000))
This will create a startAt query which would currently be 1519944842592
This means that it's trying to start at that specific number. So it's not looking for -1, it's starting the query at 1519944842592.
You would need to incorporate a createdAt object within your schema and query that first.
The reason your .orderByChild('created') works is because it's a date object which is before the startAt query so that's why it works correctly :)
I need to calculate the percentile rank of a particular value against a large number of values filtered in various different ways. The data is all stored on Parse.com, which has a limitation of returning a maximum of 1000 rows per query. The number of values stored is likely to exceed well over 100,000.
By 'percentile rank', I mean I need to calculate the percentage of values that the provided value is greater than. I am not trying to calculate the value of a provided percentile. For example, given a list of values {20, 23, 24, 29, 30, 31, 35, 40, 40, 43} the percentile rank of the provided value 35 is 70%. The algorithm for this is simply the rank of the value / count of values * 100. Not sure if 'percentile rank' is the correct terminology for this.
I have considered a couple of different approaches to this. The first is to pull down the full list of values (into Parse Cloud) and then calculate the percentile rank from there, then filter the list and calculate again, repeating the last two steps as many times as required. The problem with this approach is it will not work once we reach 1000 values, which we can expect pretty quickly.
Another option, which is the best I can come up with so far, is to query the count of items, and the rank of the provided value. For example:
var rank_world_alltime = new Parse.Query("Values")
.lessThan("value", request.params.value) // Filters query to values less than the provided value, so counting this query will return the rank
.count();
var count_world_alltime = new Parse.Query("Values")
.count();
Parse.Promise.when(rank_world_alltime, count_world_alltime).then(function(rank, count) {
percentile = rank / count * 100;
console.log("world_alltime_percentile = " + percentile);
});
This works well for a single calculation, but I need to perform multiple calculations, and this approach very quickly becomes a lot of queries. I expect to need to run about 15 calculations per call, which is 30 queries. All calculations need to complete in under 3 seconds before Parse terminates the job, and I am limited to 30 reqs/second, so this is very quickly going to become a problem.
Does anyone have any suggestions on how else I could approach this? I've thought about somehow pre-processing some of this but can't quite work out how to do so, as the filters will be based on time and location (city and country), so there are potentially a LOT of pre-calculations that will need to be run at regular intervals. The results do not need to be 100% accurate but something close.
I don't know much about parse, but as far as I understand what you say, it is some kind of cloud database thingy that holds your hiscores, and limits you 1000 rows per query, 3 seconds per job, and 30 queries per second.
In order to have approximate calculations and divide by 2 the number of queries, I would first of all cache the total (count_world_alltime, count_region,week, whatever). If you can save them somewhere locally. For numbers of 100K just getting the order of magnitude (thus not the latest updated number) should be good enough to get a percentile.
Maybe you can get several counts per query. However my lack of expertise in parse/nosql kind of stops me from being sure of this, you'll have to check their documentation. If it is possible however, for the case where you need percentiles for a serie of values all in the same category, I would
Order the values, let's call them a,b,c,d,e (once ordered)
Get the number of values between the intervals [0,a] [a,b] [b,c] [c,d] [d,e]
Use the cached total to get the percentiles (where Nxy is the number of values in [x,y]) :
Pa = 100 * N0a / total
Pb = 100 * ( N0a + Nab ) / total
Pc = 100 * ( N0a + Nab + Nbc ) / total
and so on...
If you need a value ranked worldwide, the other per region, some per week others over all times, etc, this doesn't apply. In that case I don't think you can get below 1 query/number, with caching the totals.
I am trying to figure out a formula to calculate the urgency of a set of arbitrary tasks, based on the number of days until a 'deadline' and the % completion of the task already completed.
So far I have a 'function' which gives the represents:
U = ((dd * 25) - (100 - cp))
Where:
dd = Day difference from deadline to current date (in an integer value)
cp = current completion % (in an integer value - in increments of 5 currently)
This gives me a linear function, and the 25 in the function indicates a 25% per day progression of the task.
So that at any given date:
Where U <0 task is urgent
Where U =0 task is on schedule
Where U >0 task is ahead of schedule
(The actual display on if a task is on schedule (within a range) would be handled separately)
Is there any other methods to calculate the urgency of a task, from the difference of two dates and weighted by a variable?
From current responses:
Using the start date,end date and current date differences along with completion % to calculate urgency
Possibly using a non-linear function to increase U when cp >75% and decrease U when cp < 75%. Are there any advantages for linear vs non-linear functions?
This will be used in MySQL & javascript, as I'd like a way to display how on track a task is using the U value. So finding a method to correctly (more so than my current method) calculate the value for U is what I'm attempting to do.
Solution
The solution I went with (based on marked solution):
((((((end_date - now) / (end_date - start_date)) * 100) * (100 - cp)) * 10) * -1)
Minor Changes made
Using the rule of three as a start, multiplied by 10 just to increase the values & create a wider range without needing to factor for float values too much.
Also multiplied by -1, this was so that completed tasks then give a negative number, while incomplete tasks show a higher number (makes sense: higher urgency of a task therefore a higher number)
I may in future add to this, adding a velocity for a task as suggested & also taking into account for the number of people assigned to a given task.
This function is only going to be used for a rough guide to show someone what tasks (in a given list) the might need to do first.
Also as I used this in MySQL the function needed to be wrapped in a IFNULL (due to existing data in my case)
IFNULL( *function* ,-200)
An initial arbitrary value of -200 if it was null value (as some tasks do not have an start/end date)
Thanks for the assistance & suggestions
Given that:
due is day difference from deadline to current date
estimated is the time needed for a task
done is the progress in percentage
This would be a simple rule of three:
var rest = estimated / 100 * (100 - done);
if(due < rest) {
state = 'behind';
}
if(due == rest) {
state = 'on';
}
if(due > rest) {
state = 'ahead';
}
Note that possibly very few tasks would be "on schedule" because they'd have to match exactly, you could also check in ranges like rest < due + 0.5 && rest > due - 0.5 or so, imitating a non-linear prioritizing.