2

It seems that geo_point fields are ignored in the result if specified using "fields []"

I have the following mapping for index test01

{
   "test01": {
      "mappings": {
         "activity": {
            "properties": {
               "location": {
                  "type": "string"
               },
               "mygeo": {
                  "type": "geo_point",
                  "doc_values": true,
                  "fielddata": {
                     "format": "compressed",
                     "precision": "1km"
                  }
               }
            }
         }
      }
   }
}

The index contains a single activity

{
      "mygeo": {
        "lat": 51.247607909,
        "lon": 22.565701278
      },
      "location" : "New York"
}

Query

GET /test01/_search
{
  "size" : 1,
  "fields": ["location", "mygeo"]
}

generates the following where the mygeo field is missing. (I have also tried "fields": ["location", "mygeo.lat", "mygeo.lon", "mygeo"]).

 "hits": [
     {
        "_index": "test01",
        "_type": "activity",
        "_id": "1",
        "_score": 1,
        "fields": {
           "location": [
              "New York"
           ]
        }
     }
  ]

The only way I can get the mygeo object is through _source by adding "_source" : {"includes" : [ "mygeo" ]}.

Is there any way to get a geo_point field using the "field" parameter?

I have tried the Rest API and the Java API. Both produce the same result using Elasticsearch v. 1.7.1.

Thanks

Matthias
  • 178
  • 2
  • 6

2 Answers2

2

So following the logic, I've replicated and solved the issue by adding "store": true to your index mappings and now it allows me to retrieve lon/lat using fields, rather than _source.

Please see replication done on Sense on my localhost:

DELETE test

PUT /test
{
  "mappings": {
    "test1": {
      "properties": {
        "location": {
          "type": "string"
        },
        "mygeo": {
          "type": "geo_point",
          "doc_values": true,
          "store": true, 
          "fielddata": {
            "format": "compressed",
            "precision": "1km"
          }
        }
      }
    }
  }
}

POST /test/test1/
{
  "mygeo": {
    "lat": 51.247607909,
    "lon": 22.565701278
  },
  "location": "New York"
}


GET /test/_search
{
  "size" : 1,
  "fields": ["location", "mygeo"]
}

So, this query does bring back results as you would expect. Only issue is that your lan/lon is formatted in as an array. See result from query:

{
  "hits" : [{
      "_index" : "test",
      "_type" : "test1",
      "_id" : "AVCGqhsq9y2W0mh1rPgV",
      "_score" : 1,
      "fields" : {
        "mygeo" : [
          "51.247607909,22.565701278"
        ],
        "location" : [
          "New York"
        ]
      }
    }
  ]
}

However, this is one of the formats, that Elasticsearch officially supports. Taken from documentation:

With the location field defined as a geo_point, we can proceed to index documents containing latitude/longitude pairs, which can be formatted as strings, arrays, or objects:

PUT /attractions/restaurant/1
{
  "name" : "Chipotle Mexican Grill",
  "location" : "40.715, -74.011"
}

PUT /attractions/restaurant/2
{
  "name" : "Pala Pizza",
  "location" : {
    "lat" : 40.722,
    "lon" : -73.989
  }
}

PUT /attractions/restaurant/3
{
  "name" : "Mini Munchies Pizza",
  "location" : [-73.983, 40.719]
}

Also, please note this from documentation:

Everybody gets caught at least once: string geo-points are "latitude,longitude", while array geo-points are [longitude,latitude]—the opposite order!

Evaldas Buinauskas
  • 13,739
  • 11
  • 55
  • 107
  • Strange because I don't get this error. At least not if mygeo is actually declared as a geo_point in the mapping template. Then mygeo is simply not returned without any error. I know that non-leaf nodes cannot be returned via fields but mygeo.lat and mygeo.lon are not returned either and no error is thrown. – Matthias Oct 18 '15 at 17:02
  • Apparently I did a typo in my code there. I mapped geo_type incorrect and data was inserted as strings, but I think I found how to make it work. I've updated my answer – Evaldas Buinauskas Oct 20 '15 at 19:12
  • This works the way it should. Many thanks. Any idea why "store": true has to be set for geo_point types? – Matthias Oct 22 '15 at 06:49
  • I've found question on SO discussing why you need to set `"store"` to true. Perhaps it will explain it? http://stackoverflow.com/questions/17103047/why-do-i-need-storeyes-in-elasticsearch I cannot answer this by myself, unfortunately. – Evaldas Buinauskas Oct 22 '15 at 06:52
1

If your field is stored in the _source (even if it's a GeoPoint type field), you have to use the "_source" query parameter to specify which fields (from source) you want:

GET /_search
{
    "_source": "obj.*",
    "query" : {
        "term" : { "user" : "kimchy" }
    }
}

See more details here: https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-source-filtering.html

Long story short:

  • if your field is in source, then you need to specify "_source" pattern in your query to only get the parts(fields) you want
  • Specifying "fields" in your query will (mostly) be meaningful for fields which are declared in the mapping with "store: yes". This doesn't say anything about which fields should be returned from source.
  • Yes, there's an inconsistency here: if your field is mapped in source, but not declared with "Store: yes", then specifying it in the "fields" parameter of your query may or may not return it (I've noticed that "simple" fields, such as text, number, etc are returned in this case, but more complex fields such as timestamp or GeoPoint are not).
Shivan Dragon
  • 15,004
  • 9
  • 62
  • 103