# How to define a new geo\_shape field using Painless

**URL:** https://discuss.elastic.co/t/how-to-define-a-new-geo-shape-field-using-painless/88161
**Category:** Elasticsearch
**Created:** [June 3, 2017, 9:27pm UTC](https://discuss.elastic.co/t/how-to-define-a-new-geo-shape-field-using-painless/88161 "2017-06-03T21:27:51Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![raposa](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/raposa/32/11906_2.png) [@raposa](https://discuss.elastic.co/u/raposa)
#### Post date: [June 3, 2017, 9:27pm UTC](https://discuss.elastic.co/t/how-to-define-a-new-geo-shape-field-using-painless/88161/1 "2017-06-03T21:27:51Z")

</div>

I have two float fields that represent a latitude and longitude. I want to perform an `_update_by_query` and add a new `geo_shape` field to each document using the values from the lat/lon fields.

It works easily enough for a `geo_point`:

```auto
POST my_index/_update_by_query
{
  "script" : {
    "inline" : """
ctx._source.area.location=[ctx._source.area.longitude, ctx._source.area.latitude]
"""
  }
}

```

But I cannot figure out the syntax for a `geo_shape` field. The following code does **_not_** work:

```auto
ctx._source.area.geo_shape['coordinates']=[ctx._source.area.longitude, ctx._source.area.latitude];
ctx._source.area.geo_shape['type']="point";

```

A null\_pointer\_exception is thrown on the `geo_shape` reference:

```auto
"type": "script_exception",
    "reason": "runtime error",
    "script_stack": [
      "ctx._source.area.geo_shape['coordinates']=[ctx._source.area.longitude, ctx._source.area.latitude];\n",
      " ^---- HERE"
    ],
    "script": "ctx._source.area.geo_shape['coordinates']=[ctx._source.area.longitude, ctx._source.area.latitude];\nctx._source.area.geo_shape['type']=\"point\";",
    "lang": "painless",
    "caused_by": {
      "type": "null_pointer_exception",
      "reason": null
    }

```

The mapping looks like:

```auto
"properties": {
          "area": {
            "properties": {
              "geo_shape": {
                "type": "geo_shape"
              },
              "latitude": {
                "type": "float"
              },
              "location": {
                "type": "geo_point"
              },
              "longitude": {
                "type": "float"
              },
              ...

```

Anyone tried this before?

---

<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: [June 5, 2017, 5:36pm UTC](https://discuss.elastic.co/t/how-to-define-a-new-geo-shape-field-using-painless/88161/2 "2017-06-05T17:36:40Z")

</div>

The `ctx._source` is a Map. It will not auto create fields. So you would either have to create sub maps (containing `area` and `geo_shape` keys), or just create a single field from the root (the dots will automatically be handled when indexing). Eg:

```auto
ctx._source['area.geo_shape.coordinates'] = // whatever

```

You should also aware that coordinates for a geo shape must be in an array, but what you have in your example is a geo json array, so you need to double it. Also not that this will never work, you cannot set mappings inside a document:

```auto
ctx._source.area.geo_shape['type']="point";

```

Finally, why are you using a `geo_shape` for a single point? You should use a `geo_point`.

---

<div class="post-metadata">

### Author: ![raposa](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/raposa/32/11906_2.png) [@raposa](https://discuss.elastic.co/u/raposa)
#### Post date: [June 6, 2017, 11:49am UTC](https://discuss.elastic.co/t/how-to-define-a-new-geo-shape-field-using-painless/88161/3 "2017-06-06T11:49:30Z")

</div>

I am trying to use the `geo_shape` query to determine if a point is located within a preindexed set of `geo_shape`s. `geo_point` doesn't work in that scenario.

FWIW, if the document already has a `geo_shape` field defined, I can use Painless to update the coordinates and the type. The following code works fine:

```auto
PUT test/doc/1
{
  "lon" : -87.942655,
  "lat" : 42.034714,
  "my_geo_shape" : {
    "coordinates" : [0,0],
    "type" : "point"
  }
}

POST test/_update_by_query
{
  "script" : {
    "inline": """
ctx._source.my_geo_shape.coordinates = [ctx._source.lon,ctx._source.lat];
ctx._source.my_geo_shape.type="point";
"""    
  }
}

```

What I really want is for my script to add a new `geo_shape` field to the doc, but if I run the `_update_by_query` above on the following document, I get a null\_pointer\_exception:

```auto
PUT test/doc/2
{
  "lon" : -87.942655,
  "lat" : 42.034714
}

```

What is the syntax for adding a new `geo_shape` field to a document in Painless?

---

<div class="post-metadata">

### Author: ![raposa](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/raposa/32/11906_2.png) [@raposa](https://discuss.elastic.co/u/raposa)
#### Post date: [June 6, 2017, 8:15pm UTC](https://discuss.elastic.co/t/how-to-define-a-new-geo-shape-field-using-painless/88161/4 "2017-06-06T20:15:27Z")

</div>

FWIW: I could not figure out the Painless syntax, so I just moved the work back to Logstash and reindexed. Here is what the Logstash config looked like:

```auto
   if(![area][latitude] or ![area][longitude]) {
      mutate {
      	 replace => {"[area][latitude]" => "0"}
   	     replace => {"[area][longitude]" => "0"}
	  }
   }
   
   mutate {
   	add_field => {
   		"[area][my_geoshape][coordinates]" => ["%{[area][longitude]}","%{[area][latitude]}"]
   		"[area][my_geoshape][type]" => "point"
    }
   }

```

---

<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: [June 6, 2017, 9:07pm UTC](https://discuss.elastic.co/t/how-to-define-a-new-geo-shape-field-using-painless/88161/5 "2017-06-06T21:07:55Z")

</div>

Did you try what I suggested earlier, using the full key instead of assuming auto object creation?

```auto
ctx._source['area.geo_shape.coordinates'] = [ctx._source.lon, ctx._source.lat]
ctx._source['area.geo_shape.type'] = 'point'

```

Also, I misread your "type" earlier, thinking it was trying to set the mappings, but in fact it is just a part of the geo shape.

---

<div class="post-metadata">

### Author: ![raposa](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/raposa/32/11906_2.png) [@raposa](https://discuss.elastic.co/u/raposa)
#### Post date: [June 6, 2017, 10:17pm UTC](https://discuss.elastic.co/t/how-to-define-a-new-geo-shape-field-using-painless/88161/6 "2017-06-06T22:17:55Z")

</div>

I did try that. It generates the following error:

```auto
"cause": {
        "type": "mapper_parsing_exception",
        "reason": "Could not dynamically add mapping for field [area.geo_shape.coordinates]. Existing mapping for [area.geo_shape] must be of type object but found [geo_shape]."
      }

```

---

<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: [June 7, 2017, 3:24am UTC](https://discuss.elastic.co/t/how-to-define-a-new-geo-shape-field-using-painless/88161/7 "2017-06-07T03:24:53Z")

</div>

Ok, then try:

```auto
ctx._source['area.geo_shape'] = [
  'type': 'point',
  'coordinates': [ctx._source.lon, ctx._source.lat]
]

```

---

<div class="post-metadata">

### Author: ![raposa](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/raposa/32/11906_2.png) [@raposa](https://discuss.elastic.co/u/raposa)
#### Post date: [June 7, 2017, 4:16am UTC](https://discuss.elastic.co/t/how-to-define-a-new-geo-shape-field-using-painless/88161/8 "2017-06-07T04:16:15Z")

</div>

Brilliant! That worked perfectly. Thanks for helping out with this!

---

<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: [July 5, 2017, 4:16am UTC](https://discuss.elastic.co/t/how-to-define-a-new-geo-shape-field-using-painless/88161/9 "2017-07-05T04:16:30Z")

</div>

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