# Painless: Collection.contains() not working

**URL:** <https://discuss.elastic.co/t/painless-collection-contains-not-working/178944>\
**Category:** Elasticsearch\
**Created:** [April 29, 2019, 1:38pm UTC](https://discuss.elastic.co/t/painless-collection-contains-not-working/178944 "2019-04-29T13:38:01Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![alex\_b](https://avatars.discourse-cdn.com/v4/letter/a/5f8ce5/32.png) [@alex\_b](https://discuss.elastic.co/u/alex_b)\
**Post date:** [April 29, 2019, 1:38pm UTC](https://discuss.elastic.co/t/painless-collection-contains-not-working/178944/1 "2019-04-29T13:38:01Z")

</div>

I have a simple test object indexed. It has a collection "IntCollection" and the indexed object has this property set to the array {1, 2, 3, 4, 5}. Here is the (simplified) indexed object:

```auto
"_source": 
{
  // ...
  "IntCollection": [
	1,
	2,
	3,
	4,
	5
  ]
}

```

The goal is to filter the indexed objects by containing a specific value in "IntCollection" using Painless.  
Here is my query (in Kibana):

```auto
GET /testdatatype_unit_tests/_search
{ "size": 100, 
  "query": {
  "script": {
    "script": {
      "source": "doc['IntCollection'].values.contains(1)",
      "lang": "painless"
    }
  }
}
}

```

No results are returned, although the indexed document has the searched value inside. Here is the query result:

```auto
{
  "took": 0,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 0,
    "max_score": null,
    "hits": []
  }
}

```

When I do the same request with a TermQuery, it works:

```auto
GET /testdatatype_unit_tests/_search
{ "size": 100, 
  "query": {
  "term": {
      "IntCollection": {
        "value": 1
      }
    }
  }
}

```

Any idea, what is wrong with the Painless script?

Edit: ES version 6.4.2 is used.

---

<div class="post-metadata">

**Author:** ![abdon](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/abdon/32/9195_2.png) [@abdon](https://discuss.elastic.co/u/abdon)\
**Post date:** [April 29, 2019, 3:27pm UTC](https://discuss.elastic.co/t/painless-collection-contains-not-working/178944/2 "2019-04-29T15:27:38Z")

</div>

Because Elasticsearch treats those numbers as Longs by default, you need to make sure that you pass a Long to the `contains` method. The following should work:

```auto
GET testdatatype_unit_tests/_search
{
  "size": 100,
  "query": {
    "script": {
      "script": {
        "source": "doc['IntCollection'].values.contains(1L)",
        "lang": "painless"
      }
    }
  }
}

```

---

<div class="post-metadata">

**Author:** ![alex\_b](https://avatars.discourse-cdn.com/v4/letter/a/5f8ce5/32.png) [@alex\_b](https://discuss.elastic.co/u/alex_b)\
**Post date:** [April 30, 2019, 6:28am UTC](https://discuss.elastic.co/t/painless-collection-contains-not-working/178944/3 "2019-04-30T06:28:24Z")

</div>

> [@abdon](#):
>
> Because Elasticsearch treats those numbers as Longs by default, you need to make sure that you pass a Long to the `contains` method.

It helped. Thank you!

In the same context I have another issue. My test object contains another collection with nullable integers:

```auto
"_source": 
{
  // ...
  "NullableIntCollection": [
	1,
	null,
	3,
	4,
	null
  ]
}

```

The task is to query, if the NullableIntCollection contains a null. For such queries, I use the negated ExistsQuery for simple properties, which works fine, but it does not apply to collection items. My thought was to use a script once again, but it is not working:

```auto
GET /testdatatype_unit_tests/_search
{ "size": 100, 
  "query": {
  "script": {
    "script": {
      "lang": "painless",
      "source": "doc['NullableIntCollection'].values.contains(null)"
    }
  }
}
}

```

Is something missing in the script?

---

<div class="post-metadata">

**Author:** ![abdon](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/abdon/32/9195_2.png) [@abdon](https://discuss.elastic.co/u/abdon)\
**Post date:** [April 30, 2019, 9:15am UTC](https://discuss.elastic.co/t/painless-collection-contains-not-working/178944/4 "2019-04-30T09:15:04Z")

</div>

`doc['NullableIntCollection'].values` in your script will only contain actual values. In your example it is exactly as if you had indexed the following field:

```auto
  "NullableIntCollection": [
	1,
	3,
	4
  ]

```

As a solution, maybe you can define a [`null_value`](https://www.elastic.co/guide/en/elasticsearch/reference/current/null-value.html) in your mappings for this field? A null\_value is a "default value" assigned to fields that have a value `null`. For example, if you know your collection will only contain positive numbers, you could define a `null_value` of `-1` and check for that value:

```auto
PUT testdatatype_unit_tests
{
  "mappings": {
    "_doc": {
      "properties": {
        "NullableIntCollection": {
          "type": "long",
          "null_value": -1
        }
      }
    }
  }
}

PUT testdatatype_unit_tests/_doc/1
{
  "NullableIntCollection": [
    1,
    null,
    3,
    4,
    null
  ]
}

GET testdatatype_unit_tests/_search
{
  "size": 100,
  "query": {
    "script": {
      "script": {
        "source": "doc['NullableIntCollection'].values.contains(-1L)",
        "lang": "painless"
      }
    }
  }
}

```

---

<div class="post-metadata">

**Author:** ![alex\_b](https://avatars.discourse-cdn.com/v4/letter/a/5f8ce5/32.png) [@alex\_b](https://discuss.elastic.co/u/alex_b)\
**Post date:** [April 30, 2019, 9:24am UTC](https://discuss.elastic.co/t/painless-collection-contains-not-working/178944/5 "2019-04-30T09:24:20Z")

</div>

Thank you very much once again.

---

<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:** [May 28, 2019, 9:24am UTC](https://discuss.elastic.co/t/painless-collection-contains-not-working/178944/6 "2019-05-28T09:24:24Z")

</div>

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