w3max
(Maxime Séguin)
March 24, 2017, 3:11pm
1
Hi,
I have discovered that from Elasticsearch version 5, "python language plugin" is deprecated in favor of the new default scripting language "Painless". Source: https://www.elastic.co/guide/en/elasticsearch/plugins/current/lang-python.html
Could anybody help me converting these 2 python scripts (hot ranking scripts from hacker news & reddit taken from this blog https://medium.com/hacking-and-gonzo/how-reddit-ranking-algorithms-work-ef111e33d0d9#.10tv859uq ) to Painless?
Script 1 (hacker news)
def calculate_score(votes, item_hour_age, gravity=1.8):
return (votes - 1) / pow((item_hour_age+2), gravity)
Script 2 (reddit)
from datetime import datetime, timedelta
from math import log
epoch = datetime(1970, 1, 1)
def epoch_seconds(date):
td = date - epoch
return td.days * 86400 + td.seconds + (float(td.microseconds) / 1000000)
def score(ups, downs):
return ups - downs
def hot(ups, downs, date):
s = score(ups, downs)
order = log(max(abs(s), 1), 10)
sign = 1 if s > 0 else -1 if s < 0 else 0
seconds = epoch_seconds(date) - 1134028003
return round(sign * order + seconds / 45000, 7)
I think this could be useful for a lot of people trying to understand the new "Painless" scripting language.
P.S. I am no expert in scripting or Python.
Thank you!
Maxime
nik9000
(Nik Everett)
March 24, 2017, 4:17pm
2
I haven't tested these but I believe the conversion is something like:
w3max:
def calculate_score(votes, item_hour_age, gravity=1.8):
return (votes - 1) / pow((item_hour_age+2), gravity)
This is what it'd look like if you invoked the script:
double calculateScore(long votes, double itemHourAge, double gravity) {
return (votes - 1) / Math.pow(itemHourAge + 1, gravity)
}
// Now you can call the new function:
calculateScore(doc.votes.value, doc.itemHourAge.value, 1.8)
You could replace some of the double
and long
with def
if you wanted but it'd just be slower.
w3max:
from datetime import datetime, timedelta
from math import log
epoch = datetime(1970, 1, 1)
def epoch_seconds(date):
td = date - epoch
return td.days * 86400 + td.seconds + (float(td.microseconds) / 1000000)
def score(ups, downs):
return ups - downs
def hot(ups, downs, date):
s = score(ups, downs)
order = log(max(abs(s), 1), 10)
sign = 1 if s > 0 else -1 if s < 0 else 0
seconds = epoch_seconds(date) - 1134028003
return round(sign * order + seconds / 45000, 7)
long epochSeconds(org.joda.time.ReadableDateTime date) {
return date.getMillis() / 1000
}
long score(long ups, long downs) {
return ups - downs
}
int hot(ups, downs, date) {
long s = score(ups, downs);
double order = Math.log(Math.max(abs(s), 1), 10);
long sign = Long.signum(s);
seconds = epochSeconds(date) - 1134028003;
return Math.round(sign * order + seconds / 45000, 7)
}
w3max
(Maxime Séguin)
March 24, 2017, 6:59pm
3
Thank you so much for your help!
On more question if I can. I need to have the hours since a UtcDate.
I have a createdOn property on my doc and I would like to do something like this
createdOn.getMillis() - NOW.getMillis()
I can I get NOW (DateTime in Utc)?
Thanks again!
Maxime
nik9000
(Nik Everett)
March 24, 2017, 7:12pm
4
Now is intentionally inaccessible to keep painless scripts idempotent. You should pass that information in as a script parameter.
w3max
(Maxime Séguin)
March 27, 2017, 1:40pm
5
Thank you, it works great!
system
(system)
Closed
April 24, 2017, 1:40pm
6
This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.