# Scripted update to select minimum value in list

**URL:** <https://discuss.elastic.co/t/scripted-update-to-select-minimum-value-in-list/192116>\
**Category:** Elasticsearch\
**Created:** [July 24, 2019, 6:42pm UTC](https://discuss.elastic.co/t/scripted-update-to-select-minimum-value-in-list/192116 "2019-07-24T18:42:14Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![neesha](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/neesha/32/50845_2.png) [@neesha](https://discuss.elastic.co/u/neesha)\
**Post date:** [July 24, 2019, 6:42pm UTC](https://discuss.elastic.co/t/scripted-update-to-select-minimum-value-in-list/192116/1 "2019-07-24T18:42:14Z")

</div>

I have series of documents that currently have a field that is a list of integers (date timestamps, but this doesn't really matter). Some have a single value, some have many (possibly hundreds). For example:

```auto
"date" : [1538508710]
or 
"date" : [1538405989, 1550215297, 1550236107]

```

I would like to create a script that would update all these documents and change it from being a list to being a single integer, such that the integer is the smallest value in the list. So the fields above would instead look like:

```auto
"date" : 1538508710
or
"date" : 1538405989

```

Is it possible to do this with a scripted update? Can I do something like:

```auto
"inline": "ctx._source.date = min([d for d in ctx._source.date]),",

```

---

<div class="post-metadata">

**Author:** ![rjernst](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/rjernst/32/6363_2.png) [@rjernst](https://discuss.elastic.co/u/rjernst)\
**Post date:** [July 26, 2019, 5:53pm UTC](https://discuss.elastic.co/t/scripted-update-to-select-minimum-value-in-list/192116/2 "2019-07-26T17:53:03Z")

</div>

Yes, this is possible using [update-by-query](https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update-by-query.html).

It looks like your suggested script is trying to use python generators. These are not possible in painless, but instead java streams are supported. It would look something like this:

```auto
ctx._source.date = ctx._source.date.stream().min(Comparator.comparing(Integer::valueOf)).get();

```

Note however that it is best practice to make this operation idempotent, so that if some issues causes your query to fail you will be able to restart without handling any documents already processed.

A separate (temporary) boolean field would probably be easiest for this. You can then make a second update-by-query that removes the field (where your query searches for the field existing on a document). You could also instead make your script resilient to being re-run for the same document by checking the type of ctx.\_source.date (using `instanceof List`), but whether that is easier than the first option depends on your total data size and how costly it is to rerun your update-by-query on the entire dataset.

---

<div class="post-metadata">

**Author:** ![neesha](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/neesha/32/50845_2.png) [@neesha](https://discuss.elastic.co/u/neesha)\
**Post date:** [July 29, 2019, 3:20pm UTC](https://discuss.elastic.co/t/scripted-update-to-select-minimum-value-in-list/192116/3 "2019-07-29T15:20:06Z")

</div>

> [@rjernst](#):
>
> Note however that it is best practice to make this operation idempotent, so that if some issues causes your query to fail you will be able to restart without handling any documents already processed.

Do you mean tracking which documents have already had the script run against? Is there a way to do this easily? Or are you suggesting something like if you add a new field, use the `match` part of an update query to find the documents who are missing the new field?

> [@rjernst](#):
>
> depends on your total data size and how costly it is to rerun your update-by-query on the entire dataset.

Is there a good way to estimate this cost? We've got a 40-50 million rows to update.

---

<div class="post-metadata">

**Author:** ![rjernst](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/rjernst/32/6363_2.png) [@rjernst](https://discuss.elastic.co/u/rjernst)\
**Post date:** [August 9, 2019, 10:21pm UTC](https://discuss.elastic.co/t/scripted-update-to-select-minimum-value-in-list/192116/4 "2019-08-09T22:21:00Z")

</div>

> Or are you suggesting something like if you add a new field, use the `match` part of an update query to find the documents who are missing the new field

Yes this is what I was suggesting.

> Is there a good way to estimate this cost? We've got a 40-50 million rows to update.

The best way is just to time a sample. Then you can extrapolate how long the entire update would take.

---

<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:** [September 6, 2019, 10:21pm UTC](https://discuss.elastic.co/t/scripted-update-to-select-minimum-value-in-list/192116/5 "2019-09-06T22:21:02Z")

</div>

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