# Java API Plainless script \`indexOf\` give wrong answer

**URL:** https://discuss.elastic.co/t/java-api-plainless-script-indexof-give-wrong-answer/139016
**Category:** Elasticsearch
**Created:** [July 7, 2018, 1:55pm UTC](https://discuss.elastic.co/t/java-api-plainless-script-indexof-give-wrong-answer/139016 "2018-07-07T13:55:42Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![Zt\_Zeng](https://avatars.discourse-cdn.com/v4/letter/z/b77776/32.png) [@Zt\_Zeng](https://discuss.elastic.co/u/Zt_Zeng)
#### Post date: [July 7, 2018, 1:55pm UTC](https://discuss.elastic.co/t/java-api-plainless-script-indexof-give-wrong-answer/139016/1 "2018-07-07T13:55:42Z")

</div>

Executor following script using rest way and Java API give different result:

```
  "script": {
    "inline": "ctx._source.t = params.users; ctx._source.i1= ctx._source.users.indexOf(params.users); ctx._source.i2= ctx._source.users.lastIndexOf(params.users);",
    "params": {
      "users": 540722
    }
  }

// the rest result
"t": 540722,
"i1": 0,
"i2": 105,
// the Java API result
"t1": 540722,
"i11": -1,
"i21": -1

```

what would be possible reason (version mismatch?)?

Server version: 5.6.1  
Java client: 5.5.0

* * *

Update:

Using the Java client 5.6.1  
give me the following result (still not right for `indexOf`):

```
"t1": 540722,
"i11": 105,
"i21": 105
```

---

<div class="post-metadata">

### Author: ![dadoonet](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/dadoonet/32/137187_2.png) [@dadoonet](https://discuss.elastic.co/u/dadoonet)
#### Post date: [July 7, 2018, 3:13pm UTC](https://discuss.elastic.co/t/java-api-plainless-script-indexof-give-wrong-answer/139016/2 "2018-07-07T15:13:18Z")

</div>

I'm surprised. May be try to reproduce it and share the script with us?

- One reproduction script that we can run in Kibana Dev Console.
- One java class that we can use to replay the second behavior.

---

<div class="post-metadata">

### Author: ![Zt\_Zeng](https://avatars.discourse-cdn.com/v4/letter/z/b77776/32.png) [@Zt\_Zeng](https://discuss.elastic.co/u/Zt_Zeng)
#### Post date: [July 8, 2018, 1:21am UTC](https://discuss.elastic.co/t/java-api-plainless-script-indexof-give-wrong-answer/139016/3 "2018-07-08T01:21:46Z")

</div>

kibana:

```
PUT test/test/1
{
      "users": [
      540722,
      540722,
      540722,
      540722,
      540722,
      540722,
      540722,
      540722,
      540722,
      540722,
      540722,
      540722,
      540722,
      540722,
      540722,
      540722,
      540722,
      540722,
      540722,
      540722
    ]
}
POST test/test/1/_update
{
  "script": {
    "inline": "ctx._source.t = params.users; ctx._source.i1= ctx._source.users.indexOf(params.users); ctx._source.i2= ctx._source.users.lastIndexOf(params.users);",
    "params": {
      "users": 540722
    }
  }
}
GET test/test/1

```

Part of Java code:

```
HashMap<String, Object> params = new HashMap<>();
params.put("users", 540722L);
Script painless = new Script(ScriptType.INLINE, "painless",
    "ctx._source.t1 = params.users; ctx._source.i11= ctx._source.users.indexOf(params.users); ctx._source.i21= ctx._source.users.lastIndexOf(params.users);",
    params);
UpdateRequestBuilder updateRequestBuilder = client.prepareUpdate("test", "test", "1")
    .setScript(painless);

BulkRequestBuilder bulkRequest = client.prepareBulk();
bulkRequest.add(updateRequestBuilder.request());
BulkResponse bulkItemResponses = bulkRequest.execute().actionGet();

```

We found some clue:

```
params.put("users", 540722L); // will return -1, now

params.put("users", 540722); // will work
```

---

<div class="post-metadata">

### Author: ![Zt\_Zeng](https://avatars.discourse-cdn.com/v4/letter/z/b77776/32.png) [@Zt\_Zeng](https://discuss.elastic.co/u/Zt_Zeng)
#### Post date: [July 8, 2018, 1:25am UTC](https://discuss.elastic.co/t/java-api-plainless-script-indexof-give-wrong-answer/139016/4 "2018-07-08T01:25:41Z")

</div>

And even it give the index in range, ES still complains about `ArrayIndexOutOfBound`, which is my original intuitive:

```
POST task-0/task/13031005/_update
{
  "script": {
    "inline": "ctx._source.users.remove(ctx._source.users.indexOf(params.users))",
    "params": {
      "users": 540722
    }
  }
}
```

---

<div class="post-metadata">

### Author: ![Zt\_Zeng](https://avatars.discourse-cdn.com/v4/letter/z/b77776/32.png) [@Zt\_Zeng](https://discuss.elastic.co/u/Zt_Zeng)
#### Post date: [July 10, 2018, 4:21am UTC](https://discuss.elastic.co/t/java-api-plainless-script-indexof-give-wrong-answer/139016/5 "2018-07-10T04:21:06Z")

</div>

So any plan to fix this bug because my "users" is actually long list

---

<div class="post-metadata">

### Author: ![Jack\_Conradson](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/jack_conradson/32/47236_2.png) [@Jack\_Conradson](https://discuss.elastic.co/u/Jack_Conradson)
#### Post date: [July 10, 2018, 3:34pm UTC](https://discuss.elastic.co/t/java-api-plainless-script-indexof-give-wrong-answer/139016/6 "2018-07-10T15:34:45Z")

</div>

Unfortunately this is not a simple issue to fix. someList.indexOf is based on the equivalent Java method which takes an Object and does comparisons based on that. So somewhere in the chain the users field is being parsed as both Integer and Long values (probably due to the values being unknown at the time of parsing, so anything smaller than Integer.MAX\_VALUE becomes an Integer and anything greater becomes a Long.

As a workaround for now one thing to try could be the following:

`def users = params.users = params.users < Integer.MAX_VALUE ? (int)params.users : (long)params.users; <yourlist>.indexOf(users)`

This will ensure the appropriate reference type (Integer or Long) based on the incoming value for comparison against.

---

<div class="post-metadata">

### Author: ![Zt\_Zeng](https://avatars.discourse-cdn.com/v4/letter/z/b77776/32.png) [@Zt\_Zeng](https://discuss.elastic.co/u/Zt_Zeng)
#### Post date: [July 11, 2018, 12:25am UTC](https://discuss.elastic.co/t/java-api-plainless-script-indexof-give-wrong-answer/139016/7 "2018-07-11T00:25:11Z")

</div>

But my mappings is

```
    "users": {
      "type": "long"
    }

```

Shouldn't this ensure my list to be `List<Long>`?

By the way, can I set `users` as a `hashset` and directly use `users.remove`?

---

<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 11, 2018, 1:28am UTC](https://discuss.elastic.co/t/java-api-plainless-script-indexof-give-wrong-answer/139016/8 "2018-07-11T01:28:12Z")

</div>

Painless does not have generics, so to it, you only have List (of Object). In java, if you call `Long.equals` with an `Integer`, it will always return false (boxed types do not do promotions when comparing).

---

<div class="post-metadata">

### Author: ![Zt\_Zeng](https://avatars.discourse-cdn.com/v4/letter/z/b77776/32.png) [@Zt\_Zeng](https://discuss.elastic.co/u/Zt_Zeng)
#### Post date: [July 11, 2018, 6:41am UTC](https://discuss.elastic.co/t/java-api-plainless-script-indexof-give-wrong-answer/139016/9 "2018-07-11T06:41:09Z")

</div>

So, as you said, even I use a `hashset`, `remove` will still not work, right?

---

<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 11, 2018, 7:39am UTC](https://discuss.elastic.co/t/java-api-plainless-script-indexof-give-wrong-answer/139016/10 "2018-07-11T07:39:57Z")

</div>

Right, since `remove` takes Object, unless you pass in the exact type of the boxed value you are searching for.

---

<div class="post-metadata">

### Author: ![Zt\_Zeng](https://avatars.discourse-cdn.com/v4/letter/z/b77776/32.png) [@Zt\_Zeng](https://discuss.elastic.co/u/Zt_Zeng)
#### Post date: [July 11, 2018, 9:56am UTC](https://discuss.elastic.co/t/java-api-plainless-script-indexof-give-wrong-answer/139016/11 "2018-07-11T09:56:29Z")

</div>

One more question, the elastic `array` type can be any Java collection type?

---

<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 12, 2018, 10:41pm UTC](https://discuss.elastic.co/t/java-api-plainless-script-indexof-give-wrong-answer/139016/12 "2018-07-12T22:41:42Z")

</div>

Arrays aren't a real type, they are a form that gets parsed into fields, whether they are sub fields (eg passing json objects) or concrete values in the array. As with all of a document passed to elasticsearch, it must be in json, so the limitation is whatever data types json has. See [https://www.elastic.co/guide/en/elasticsearch/reference/current/array.html](https://www.elastic.co/guide/en/elasticsearch/reference/current/array.html).

---

<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: [August 9, 2018, 10:41pm UTC](https://discuss.elastic.co/t/java-api-plainless-script-indexof-give-wrong-answer/139016/13 "2018-08-09T22:41:44Z")

</div>

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