# Help with converting scripts from python to painless

**URL:** <https://discuss.elastic.co/t/help-with-converting-scripts-from-python-to-painless/79912>\
**Category:** Elasticsearch\
**Created:** [March 24, 2017, 3:11pm UTC](https://discuss.elastic.co/t/help-with-converting-scripts-from-python-to-painless/79912 "2017-03-24T15:11:39Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![w3max](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/w3max/32/16698_2.png) [@w3max](https://discuss.elastic.co/u/w3max)\
**Post date:** [March 24, 2017, 3:11pm UTC](https://discuss.elastic.co/t/help-with-converting-scripts-from-python-to-painless/79912/1 "2017-03-24T15:11:39Z")

</div>

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](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](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

---

<div class="post-metadata">

**Author:** ![nik9000](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/nik9000/32/44947_2.png) [@nik9000](https://discuss.elastic.co/u/nik9000)\
**Post date:** [March 24, 2017, 4:17pm UTC](https://discuss.elastic.co/t/help-with-converting-scripts-from-python-to-painless/79912/2 "2017-03-24T16:17:04Z")

</div>

I haven't tested these but I believe the conversion is something like:

> [@w3max](#):
>
> ```auto
> 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:

```auto
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](#):
>
> ```auto
> 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 &gt; 0 else -1 if s &lt; 0 else 0
> seconds = epoch_seconds(date) - 1134028003
> return round(sign * order + seconds / 45000, 7)
> 
> ```

```auto
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)
}

```

---

<div class="post-metadata">

**Author:** ![w3max](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/w3max/32/16698_2.png) [@w3max](https://discuss.elastic.co/u/w3max)\
**Post date:** [March 24, 2017, 6:59pm UTC](https://discuss.elastic.co/t/help-with-converting-scripts-from-python-to-painless/79912/3 "2017-03-24T18:59:55Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![nik9000](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/nik9000/32/44947_2.png) [@nik9000](https://discuss.elastic.co/u/nik9000)\
**Post date:** [March 24, 2017, 7:12pm UTC](https://discuss.elastic.co/t/help-with-converting-scripts-from-python-to-painless/79912/4 "2017-03-24T19:12:29Z")

</div>

Now is intentionally inaccessible to keep painless scripts idempotent. You should pass that information in as a script parameter.

---

<div class="post-metadata">

**Author:** ![w3max](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/w3max/32/16698_2.png) [@w3max](https://discuss.elastic.co/u/w3max)\
**Post date:** [March 27, 2017, 1:40pm UTC](https://discuss.elastic.co/t/help-with-converting-scripts-from-python-to-painless/79912/5 "2017-03-27T13:40:12Z")

</div>

Thank you, it works great!

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [April 24, 2017, 1:40pm UTC](https://discuss.elastic.co/t/help-with-converting-scripts-from-python-to-painless/79912/6 "2017-04-24T13:40:27Z")

</div>

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.
