Repository: komoot/photon (java)

Issue:
geometries are of type feature instead of Point
With the latest addition of the GeocodeJsonFormatter file, the geojson feature collection contains features of type 'feature' instead of 'Point' as previously.

Here's an example of the geojson produced by the api:
```
{
    "features": [
      {
        "geometry": {
          "coordinates": [
            -73.53425581561339,
            45.51415475
          ],
          "type": "feature"
        },
        "type": "feature",
        "properties": {
          "osm_type": "R"
          <more properties>
        }
      }
    ],
    "type": "FeatureCollection"
}
```

Pull request description:
Fix geojson geometry type in GeocodeJsonFormatter
Fixes #656

Also use the constants instead of hard-coded strings in the
GeocodeJsonFormatter class and add unit tests for the geojson formatter.

Patch:
diff --git a/src/main/java/de/komoot/photon/elasticsearch/ElasticResult.java b/src/main/java/de/komoot/photon/elasticsearch/ElasticResult.java
index 2cfd58e..960b6d7 100644
--- a/src/main/java/de/komoot/photon/elasticsearch/ElasticResult.java
+++ b/src/main/java/de/komoot/photon/elasticsearch/ElasticResult.java
@@ -53,9 +53,9 @@ public class ElasticResult implements PhotonResult {
         final Map<String, Double> coordinate = (Map<String, Double>) result.getSource().get("coordinate");
         if (coordinate == null) {
             log.error(String.format("invalid data [id=%s, type=%s], coordinate is missing!",
-                    result.getSource().get(Constants.OSM_ID),
-                    result.getSource().get(Constants.OSM_VALUE)));
-            return INVALID_COORDINATES;
+                                    result.getSource().get(Constants.OSM_ID),
+                                    result.getSource().get(Constants.OSM_VALUE)));
+            return new double[]{Double.NaN, Double.NaN};
         }
 
         return new double[]{coordinate.get(Constants.LON), coordinate.get(Constants.LAT)};
diff --git a/src/main/java/de/komoot/photon/elasticsearch/IndexSettings.java b/src/main/java/de/komoot/photon/elasticsearch/IndexSettings.java
index 1e1ba28..2135fe9 100644
--- a/src/main/java/de/komoot/photon/elasticsearch/IndexSettings.java
+++ b/src/main/java/de/komoot/photon/elasticsearch/IndexSettings.java
@@ -19,7 +19,6 @@ import java.util.*;
  */
 public class IndexSettings {
     private final JSONObject settings;
-    private Integer numShards = null;
 
     /**
      * Create a new settings object and initialize it with the index settings
@@ -40,7 +39,9 @@ public class IndexSettings {
      * @return Return this object for chaining.
      */
     public IndexSettings setShards(Integer numShards) {
-        this.numShards = numShards;
+        if (numShards != null) {
+            settings.put("index", new JSONObject().put("number_of_shards", numShards));
+        }
 
         return this;
     }
@@ -138,18 +139,10 @@ public class IndexSettings {
      * @param indexName Name of the new index
      */
     public void createIndex(Client client, String indexName) {
-        if (numShards != null) {
-            settings.put("index", new JSONObject().put("number_of_shards", numShards));
-        }
-
         client.admin().indices().prepareCreate(indexName)
                 .setSettings(settings.toString(), XContentType.JSON)
                 .execute()
                 .actionGet();
-
-        if (numShards != null) {
-            settings.remove("index");
-        }
     }
 
     /**
diff --git a/src/main/java/de/komoot/photon/elasticsearch/Server.java b/src/main/java/de/komoot/photon/elasticsearch/Server.java
index 7196aac..b68dfe1 100644
--- a/src/main/java/de/komoot/photon/elasticsearch/Server.java
+++ b/src/main/java/de/komoot/photon/elasticsearch/Server.java
@@ -7,6 +7,7 @@ import de.komoot.photon.searcher.ReverseHandler;
 import de.komoot.photon.searcher.SearchHandler;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.SystemUtils;
+import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
 import org.elasticsearch.action.get.GetResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.client.transport.TransportClient;
@@ -22,7 +23,8 @@ import org.elasticsearch.plugins.Plugin;
 import org.elasticsearch.transport.Netty4Plugin;
 import org.elasticsearch.transport.client.PreBuiltTransportClient;
 
-import java.io.*;
+import java.io.File;
+import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.net.URISyntaxException;
 import java.net.URL;
@@ -55,10 +57,12 @@ public class Server {
 
     private Node esNode;
 
-    protected Client esClient;
+    private Client esClient;
 
     private File esDirectory;
 
+    private Integer shards = null;
+
     protected static class MyNode extends Node {
         public MyNode(Settings preparedSettings, Collection<Class<? extends Plugin>> classpathPlugins) {
             super(InternalSettingsPreparer.prepareEnvironment(preparedSettings, null), classpathPlugins);
@@ -203,11 +207,11 @@ public class Server {
         }
     }
 
-    protected IndexSettings loadIndexSettings() {
-        return new IndexSettings();
+    private IndexSettings loadIndexSettings() {
+        return new IndexSettings().setShards(shards);
     }
 
-    private void deleteIndex() {
+    public void deleteIndex() {
         try {
             esClient.admin().indices().prepareDelete(PhotonIndex.NAME).execute().actionGet();
         } catch (IndexNotFoundException e) {
@@ -216,7 +220,20 @@ public class Server {
     }
 
 
-   /**
+    /**
+     * Set the maximum number of shards for the embedded node
+     * This typically only makes sense for testing
+     *
+     * @param shards the maximum number of shards
+     * @return this Server instance for chaining
+     */
+    public Server setMaxShards(Integer shards) {
+        this.shards = shards;
+        return this;
+    }
+
+
+       /**
      * Save the global properties to the database.
      *
      * The function saved properties available as members and the database version
@@ -265,6 +282,14 @@ public class Server {
         dbProperties.setLanguages(langString == null ? null : langString.split(","));
     }
 
+    public GetResponse getById(int id) {
+        return esClient.prepareGet(PhotonIndex.NAME,PhotonIndex.TYPE, String.valueOf(id)).execute().actionGet();
+    }
+
+    public void refresh() {
+        esClient.admin().indices().refresh(new RefreshRequest(PhotonIndex.NAME)).actionGet();
+    }
+
     public Importer createImporter(String[] languages, String[] extraTags) {
         return new de.komoot.photon.elasticsearch.Importer(esClient, languages, extraTags);
     }
diff --git a/src/main/java/de/komoot/photon/searcher/GeocodeJsonFormatter.java b/src/main/java/de/komoot/photon/searcher/GeocodeJsonFormatter.java
index a9df3b7..635dcce 100644
--- a/src/main/java/de/komoot/photon/searcher/GeocodeJsonFormatter.java
+++ b/src/main/java/de/komoot/photon/searcher/GeocodeJsonFormatter.java
@@ -30,10 +30,10 @@ public class GeocodeJsonFormatter implements ResultFormatter {
             final double[] coordinates = result.getCoordinates();
 
             features.put(new JSONObject()
-                        .put("type", "feature")
+                        .put("type", "Feature")
                         .put("properties", getResultProperties(result))
                         .put("geometry", new JSONObject()
-                                .put("type", "feature")
+                                .put("type", "Point")
                                 .put("coordinates", coordinates)));
         }
 
diff --git a/src/main/java/de/komoot/photon/searcher/PhotonResult.java b/src/main/java/de/komoot/photon/searcher/PhotonResult.java
index e97de62..a68588e 100644
--- a/src/main/java/de/komoot/photon/searcher/PhotonResult.java
+++ b/src/main/java/de/komoot/photon/searcher/PhotonResult.java
@@ -6,7 +6,6 @@ import java.util.Map;
  * A single response object from the database.
  */
 public interface PhotonResult {
-    public double[] INVALID_COORDINATES = new double[]{0, 0};
 
     /**
      * Get the value for the given field.


Test patch:
diff --git a/src/test/java/de/komoot/photon/ESBaseTester.java b/src/test/java/de/komoot/photon/ESBaseTester.java
index 48bc34e..ee57d54 100644
--- a/src/test/java/de/komoot/photon/ESBaseTester.java
+++ b/src/test/java/de/komoot/photon/ESBaseTester.java
@@ -4,14 +4,13 @@ import com.vividsolutions.jts.geom.Coordinate;
 import com.vividsolutions.jts.geom.GeometryFactory;
 import com.vividsolutions.jts.geom.Point;
 import com.vividsolutions.jts.geom.PrecisionModel;
-import de.komoot.photon.elasticsearch.ElasticTestServer;
-import de.komoot.photon.searcher.PhotonResult;
+import de.komoot.photon.elasticsearch.Server;
 import lombok.extern.slf4j.Slf4j;
+import org.elasticsearch.action.get.GetResponse;
 import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.io.TempDir;
 
+import java.io.File;
 import java.io.IOException;
-import java.nio.file.Path;
 import java.util.Collections;
 
 /**
@@ -21,40 +20,38 @@ import java.util.Collections;
  */
 @Slf4j
 public class ESBaseTester {
-    @TempDir
-    protected Path dataDirectory;
-
     public static final String TEST_CLUSTER_NAME = "photon-test";
-    protected static GeometryFactory FACTORY = new GeometryFactory(new PrecisionModel(), 4326);
+    private static GeometryFactory FACTORY = new GeometryFactory(new PrecisionModel(), 4326);
 
-    private ElasticTestServer server;
+    private Server server;
 
     protected PhotonDoc createDoc(double lon, double lat, int id, int osmId, String key, String value) {
         Point location = FACTORY.createPoint(new Coordinate(lon, lat));
         return new PhotonDoc(id, "W", osmId, key, value).names(Collections.singletonMap("name", "berlin")).centroid(location);
     }
 
-    protected PhotonResult getById(int id) {
+    protected GetResponse getById(int id) {
         return server.getById(id);
     }
 
 
     @AfterEach
     public void tearDown() {
+        deleteIndex();
         shutdownES();
     }
 
     public void setUpES() throws IOException {
-        setUpES(dataDirectory, "en");
+        setUpES("en");
     }
     /**
      * Setup the ES server
      *
      * @throws IOException
      */
-    public void setUpES(Path test_directory, String... languages) throws IOException {
-        server = new ElasticTestServer(test_directory.toString());
-        server.start(TEST_CLUSTER_NAME, new String[]{});
+    public void setUpES(String... languages) throws IOException {
+        server = new Server(new File("./target/es_photon_test").getAbsolutePath()).setMaxShards(1).start(TEST_CLUSTER_NAME, new String[]{});
+        deleteIndex(); // just in case of an abnormal abort previously
         server.recreateIndex(languages);
         refresh();
     }
@@ -79,7 +76,7 @@ public class ESBaseTester {
         return server.createUpdater(new String[]{"en"}, extraTags);
     }
 
-    protected ElasticTestServer getServer() {
+    protected Server getServer() {
         if (server == null) {
             throw new RuntimeException("call setUpES before using getClient");
         }
@@ -98,4 +95,9 @@ public class ESBaseTester {
         if (server != null)
             server.shutdown();
     }
+
+    public void deleteIndex() {
+        if (server != null)
+            server.deleteIndex();
+    }
 }
diff --git a/src/test/java/de/komoot/photon/PhotonDocTest.java b/src/test/java/de/komoot/photon/PhotonDocTest.java
index 4784edb..a3d301f 100644
--- a/src/test/java/de/komoot/photon/PhotonDocTest.java
+++ b/src/test/java/de/komoot/photon/PhotonDocTest.java
@@ -1,10 +1,10 @@
 package de.komoot.photon;
 
+import java.util.HashMap;
+
 import de.komoot.photon.nominatim.model.AddressType;
 import org.junit.jupiter.api.Test;
 
-import java.util.HashMap;
-
 import static org.junit.jupiter.api.Assertions.*;
 
 public class PhotonDocTest {
diff --git a/src/test/java/de/komoot/photon/elasticsearch/DatabasePropertiesTest.java b/src/test/java/de/komoot/photon/elasticsearch/DatabasePropertiesTest.java
index b366a69..f665460 100644
--- a/src/test/java/de/komoot/photon/elasticsearch/DatabasePropertiesTest.java
+++ b/src/test/java/de/komoot/photon/elasticsearch/DatabasePropertiesTest.java
@@ -4,6 +4,8 @@ import de.komoot.photon.DatabaseProperties;
 import de.komoot.photon.ESBaseTester;
 import org.junit.jupiter.api.Test;
 
+import java.io.IOException;
+
 import static org.junit.jupiter.api.Assertions.*;
 
 /**
diff --git a/src/test/java/de/komoot/photon/elasticsearch/ElasticGetIdResult.java b/src/test/java/de/komoot/photon/elasticsearch/ElasticGetIdResult.java
deleted file mode 100644
index 715146b..0000000
--- a/src/test/java/de/komoot/photon/elasticsearch/ElasticGetIdResult.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package de.komoot.photon.elasticsearch;
-
-import de.komoot.photon.searcher.PhotonResult;
-import org.apache.commons.lang3.NotImplementedException;
-import org.elasticsearch.action.get.GetResponse;
-
-import java.util.Map;
-
-public class ElasticGetIdResult implements PhotonResult {
-
-    private final GetResponse result;
-
-    ElasticGetIdResult(GetResponse result) {
-        this.result = result;
-    }
-    @Override
-    public Object get(String key) {
-        return result.getSource().get(key);
-    }
-
-    @Override
-    public String getLocalised(String key, String language) {
-        throw new NotImplementedException();
-    }
-
-    @Override
-    public Map<String, String> getMap(String key) {
-        return (Map<String, String>) result.getSource().get(key);
-    }
-
-    @Override
-    public double[] getCoordinates() {
-        throw new NotImplementedException();
-    }
-
-    @Override
-    public double[] getExtent() {
-        throw new NotImplementedException();
-    }
-
-    @Override
-    public double getScore() {
-        throw new NotImplementedException();
-    }
-}
diff --git a/src/test/java/de/komoot/photon/elasticsearch/ElasticResultTest.java b/src/test/java/de/komoot/photon/elasticsearch/ElasticResultTest.java
deleted file mode 100644
index 71e879f..0000000
--- a/src/test/java/de/komoot/photon/elasticsearch/ElasticResultTest.java
+++ /dev/null
@@ -1,138 +0,0 @@
-package de.komoot.photon.elasticsearch;
-
-import com.vividsolutions.jts.geom.Coordinate;
-import com.vividsolutions.jts.geom.Envelope;
-import com.vividsolutions.jts.geom.Point;
-import de.komoot.photon.ESBaseTester;
-import de.komoot.photon.Importer;
-import de.komoot.photon.PhotonDoc;
-import de.komoot.photon.query.PhotonRequest;
-import de.komoot.photon.searcher.PhotonResult;
-import de.komoot.photon.searcher.SearchHandler;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestInstance;
-import org.junit.jupiter.api.io.TempDir;
-
-import java.nio.file.Path;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-@TestInstance(TestInstance.Lifecycle.PER_CLASS)
-public class ElasticResultTest  extends ESBaseTester {
-    @TempDir
-    private static Path instanceTestDirectory;
-
-    private Map<String, String> makeMap(String... kv) {
-        Map<String, String> result = new HashMap<>();
-        for (int i = 0; i < kv.length; i += 2) {
-            result.put(kv[i], kv[i + 1]);
-        }
-
-        return result;
-    }
-
-    protected PhotonDoc createDoc(double lon, double lat, int id, int osmId, String key, String value) {
-        Point location = FACTORY.createPoint(new Coordinate(lon, lat));
-        return new PhotonDoc(id, "W", osmId, key, value).centroid(location);
-    }
-
-
-    @BeforeAll
-    public void setUp() throws Exception {
-        setUpES(instanceTestDirectory, "en", "de", "fr", "it");
-        Importer instance = getServer().createImporter(new String[]{"en", "de", "fr", "it"},
-                 new String[]{"population",  "capital"});
-
-        instance.add(createDoc(45.2, -7.45, 123, 1123, "place", "city")
-                .names(makeMap("name", "München", "name:it", "Monacco", "name:en", "Munich"))
-                .address(Collections.singletonMap("state", "Bavaria"))
-                .countryCode("de")
-                .extraTags(makeMap("population", "many", "capital", "yes", "maxage", "99")));
-        instance.add(createDoc(0, 0, 99, 11999, "place", "locality")
-                .names(makeMap("name", "null island")));
-        instance.add(createDoc(-179, 1.0001, 923, 1923, "place", "house")
-                .houseNumber("34")
-                .bbox(FACTORY.createMultiPoint(new Coordinate[]{new Coordinate(-179.5, 1.0),
-                        new Coordinate(-178.5, 1.1)}))
-                .address(makeMap("street", "Hauptstr", "city", "Hamburg")));
-        instance.add(new PhotonDoc(42, "N", 42, "place", "hamlet")
-                .names(makeMap("name", "nowhere")));
-
-        instance.finish();
-        refresh();
-    }
-
-    @AfterAll
-    @Override
-    public void tearDown() {
-        super.tearDown();
-    }
-
-    private PhotonResult search(String query) {
-        SearchHandler handler = getServer().createSearchHandler(new String[]{"en", "de", "it"});
-
-        return handler.search(new PhotonRequest(query, "default")).get(0);
-    }
-
-
-    @Test
-    public void testGet() {
-        PhotonResult result = search("München");
-
-        assertAll("get",
-                () -> assertEquals("DE", result.get("countrycode")),
-                () -> assertNull(result.get("horse"))
-        );
-    }
-
-    @Test
-    public void testGetMap() {
-        assertAll("getMap",
-                () -> assertEquals(makeMap("default", "München", "en", "Munich", "it", "Monacco"),
-                                   search("München").getMap("name")),
-                () -> assertEquals(makeMap("default", "null island"),
-                                   search("null island").getMap("name")),
-                () -> assertNull(search("Hauptstr 34").getMap("name")),
-                () -> assertEquals(makeMap("population", "many", "capital", "yes"),
-                                   search("München").getMap("extra"))
-        );
-    }
-
-    @Test
-    public void testGetLocalized() {
-        PhotonResult result = search("München");
-
-        assertAll("getLocalized",
-                () -> assertEquals("Munich", result.getLocalised("name", "en")),
-                () -> assertEquals("München", result.getLocalised("name", "fr")),
-                () -> assertEquals("Monacco", result.getLocalised("name", "it")),
-                () -> assertNull(result.getLocalised("city", "en"))
-        );
-    }
-
-    @Test
-    public void testGetCoordinates() {
-        assertAll("getCoordinates",
-                () -> assertArrayEquals(new double[]{-179, 1.0001}, search("Hauptstr 34").getCoordinates()),
-                () -> assertArrayEquals(PhotonResult.INVALID_COORDINATES, search("nowhere").getCoordinates())
-        );
-    }
-
-    @Test
-    public void testGetExtent() {
-        assertAll("getExtent",
-                () -> assertNull(search("Munich").getExtent()),
-                () -> assertArrayEquals(new double[]{-179.5, 1.1, -178.5, 1.0}, search("hauptstr 34").getExtent())
-        );
-    }
-
-    @Test
-    public void testGetScore() {
-        assertTrue(Double.isFinite(search("null island").getScore()));
-    }
-}
diff --git a/src/test/java/de/komoot/photon/elasticsearch/ElasticTestServer.java b/src/test/java/de/komoot/photon/elasticsearch/ElasticTestServer.java
deleted file mode 100644
index c9bfd03..0000000
--- a/src/test/java/de/komoot/photon/elasticsearch/ElasticTestServer.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package de.komoot.photon.elasticsearch;
-
-import de.komoot.photon.searcher.PhotonResult;
-import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
-import org.elasticsearch.action.get.GetResponse;
-
-public class ElasticTestServer extends Server {
-    public ElasticTestServer(String mainDirectory) {
-        super(mainDirectory);
-    }
-
-    @Override
-    protected IndexSettings loadIndexSettings() {
-        return new IndexSettings().setShards(1);
-    }
-
-    public PhotonResult getById(int id) {
-        GetResponse response =  esClient.prepareGet(PhotonIndex.NAME,PhotonIndex.TYPE, String.valueOf(id)).execute().actionGet();
-
-        return response.isExists() ? new ElasticGetIdResult(response) : null;
-    }
-
-    public void refresh() {
-        esClient.admin().indices().refresh(new RefreshRequest(PhotonIndex.NAME)).actionGet();
-    }
-}
diff --git a/src/test/java/de/komoot/photon/elasticsearch/ImporterTest.java b/src/test/java/de/komoot/photon/elasticsearch/ImporterTest.java
index b6866b2..521a568 100644
--- a/src/test/java/de/komoot/photon/elasticsearch/ImporterTest.java
+++ b/src/test/java/de/komoot/photon/elasticsearch/ImporterTest.java
@@ -1,9 +1,9 @@
 package de.komoot.photon.elasticsearch;
 
 import de.komoot.photon.ESBaseTester;
-import de.komoot.photon.Importer;
 import de.komoot.photon.PhotonDoc;
-import de.komoot.photon.searcher.PhotonResult;
+import de.komoot.photon.Importer;
+import org.elasticsearch.action.get.GetResponse;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
@@ -30,16 +30,18 @@ public class ImporterTest extends ESBaseTester {
         instance.finish();
         refresh();
 
-        PhotonResult response = getById(1234);
+        GetResponse response = getById(1234);
+
+        assertTrue(response.isExists());
 
-        assertNotNull(response);
+        Map<String, Object> source = response.getSource();
 
-        assertEquals("N", response.get("osm_type"));
-        assertEquals(1000, response.get("osm_id"));
-        assertEquals("place", response.get("osm_key"));
-        assertEquals("city", response.get("osm_value"));
+        assertEquals("N", source.get("osm_type"));
+        assertEquals(1000, source.get("osm_id"));
+        assertEquals("place", source.get("osm_key"));
+        assertEquals("city", source.get("osm_value"));
 
-        assertNull(response.get("extra"));
+        assertNull(source.get("extra"));
     }
 
     @Test
@@ -57,10 +59,10 @@ public class ImporterTest extends ESBaseTester {
         instance.finish();
         refresh();
 
-        PhotonResult response = getById(1234);
-        assertNotNull(response);
+        GetResponse response = getById(1234);
+        assertTrue(response.isExists());
 
-        Map<String, String> extra = response.getMap("extra");
+        Map<String, String> extra = (Map<String, String>) response.getSource().get("extra");
         assertNotNull(extra);
 
         assertEquals(2, extra.size());
@@ -68,8 +70,8 @@ public class ImporterTest extends ESBaseTester {
         assertEquals("foo", extra.get("website"));
 
         response = getById(1235);
-        assertNotNull(response);
+        assertTrue(response.isExists());
 
-        assertNull(response.get("extra"));
+        assertNull(response.getSource().get("extra"));
     }
 }
\ No newline at end of file
diff --git a/src/test/java/de/komoot/photon/elasticsearch/UpdaterTest.java b/src/test/java/de/komoot/photon/elasticsearch/UpdaterTest.java
index f8b1179..02ee605 100644
--- a/src/test/java/de/komoot/photon/elasticsearch/UpdaterTest.java
+++ b/src/test/java/de/komoot/photon/elasticsearch/UpdaterTest.java
@@ -1,10 +1,10 @@
 package de.komoot.photon.elasticsearch;
 
 import de.komoot.photon.ESBaseTester;
-import de.komoot.photon.Importer;
 import de.komoot.photon.PhotonDoc;
+import de.komoot.photon.Importer;
 import de.komoot.photon.Updater;
-import de.komoot.photon.searcher.PhotonResult;
+import org.elasticsearch.action.get.GetResponse;
 import org.junit.jupiter.api.Test;
 
 import java.io.IOException;
@@ -34,10 +34,10 @@ public class UpdaterTest extends ESBaseTester {
         updater.finish();
         refresh();
 
-        PhotonResult response = getById(1234);
-        assertNotNull(response);
+        GetResponse response = getById(1234);
 
-        Map<String, String> out_names = response.getMap("name");
+        assertTrue(response.isExists());
+        Map<String, String> out_names = (Map<String, String>) response.getSourceAsMap().get("name");
         assertEquals("Foo", out_names.get("default"));
         assertEquals("Enfoo", out_names.get("en"));
     }
@@ -61,10 +61,10 @@ public class UpdaterTest extends ESBaseTester {
         updater.finish();
         refresh();
 
-        PhotonResult response = getById(1234);
-        assertNotNull(response);
+        GetResponse response = getById(1234);
 
-        Map<String, String> out_names = response.getMap("name");
+        assertTrue(response.isExists());
+        Map<String, String> out_names = (Map<String, String>) response.getSourceAsMap().get("name");
         assertFalse(out_names.containsKey("default"));
         assertEquals("Enfoo", out_names.get("en"));
     }
@@ -81,10 +81,10 @@ public class UpdaterTest extends ESBaseTester {
         instance.finish();
         refresh();
 
-        PhotonResult response = getById(1234);
-        assertNotNull(response);
+        GetResponse response = getById(1234);
+        assertTrue(response.isExists());
 
-        assertNull(response.get("extra"));
+        assertNull(response.getSource().get("extra"));
 
         doc.extraTags(Collections.singletonMap("website", "http://site.foo"));
         Updater updater = makeUpdaterWithExtra("website");
@@ -93,9 +93,9 @@ public class UpdaterTest extends ESBaseTester {
         refresh();
 
         response = getById(1234);
-        assertNotNull(response);
+        assertTrue(response.isExists());
 
-        Map<String, String> extra = response.getMap("extra");
+        Map<String, String> extra = (Map<String, String>) response.getSource().get("extra");
 
         assertNotNull(extra);
         assertEquals(Collections.singletonMap("website", "http://site.foo"), extra);
diff --git a/src/test/java/de/komoot/photon/nominatim/testdb/PlacexTestRow.java b/src/test/java/de/komoot/photon/nominatim/testdb/PlacexTestRow.java
index 08e9218..f8598fd 100644
--- a/src/test/java/de/komoot/photon/nominatim/testdb/PlacexTestRow.java
+++ b/src/test/java/de/komoot/photon/nominatim/testdb/PlacexTestRow.java
@@ -5,12 +5,13 @@ import com.vividsolutions.jts.io.WKTReader;
 import de.komoot.photon.PhotonDoc;
 import lombok.Getter;
 import org.json.JSONObject;
-import org.junit.jupiter.api.Assertions;
 import org.springframework.jdbc.core.JdbcTemplate;
 
 import java.util.HashMap;
 import java.util.Map;
 
+import org.junit.jupiter.api.Assertions;
+
 @Getter
 public class PlacexTestRow {
     private static final WKTReader wkt = new WKTReader();
diff --git a/src/test/java/de/komoot/photon/query/PhotonRequestFactoryTest.java b/src/test/java/de/komoot/photon/query/PhotonRequestFactoryTest.java
index 4dc2c0a..6363d17 100644
--- a/src/test/java/de/komoot/photon/query/PhotonRequestFactoryTest.java
+++ b/src/test/java/de/komoot/photon/query/PhotonRequestFactoryTest.java
@@ -1,6 +1,10 @@
 package de.komoot.photon.query;
 
 import com.vividsolutions.jts.geom.Envelope;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.params.provider.Arguments.arguments;
+
 import de.komoot.photon.searcher.TagFilter;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
@@ -13,9 +17,6 @@ import spark.Request;
 import java.util.*;
 import java.util.stream.Stream;
 
-import static org.junit.jupiter.api.Assertions.*;
-import static org.junit.jupiter.params.provider.Arguments.arguments;
-
 /**
  * Tests for correct parsing of the query parameters into a PhotonRequest.
  */
diff --git a/src/test/java/de/komoot/photon/query/QueryByClassificationTest.java b/src/test/java/de/komoot/photon/query/QueryByClassificationTest.java
index 59c962f..0d63d9a 100644
--- a/src/test/java/de/komoot/photon/query/QueryByClassificationTest.java
+++ b/src/test/java/de/komoot/photon/query/QueryByClassificationTest.java
@@ -3,6 +3,7 @@ package de.komoot.photon.query;
 import de.komoot.photon.*;
 import de.komoot.photon.searcher.PhotonResult;
 import lombok.extern.slf4j.Slf4j;
+import org.elasticsearch.action.get.GetResponse;
 import org.json.JSONArray;
 import org.json.JSONObject;
 import org.junit.jupiter.api.BeforeEach;
@@ -61,6 +62,7 @@ public class QueryByClassificationTest extends ESBaseTester {
             throw new RuntimeException(e);
         }
         try {
+            getServer().setMaxShards(null);
             getServer().updateIndexSettings(synonymPath.toString());
         } catch (IOException e) {
             throw new RuntimeException(e);
@@ -80,8 +82,8 @@ public class QueryByClassificationTest extends ESBaseTester {
 
         assertNotNull(class_term);
 
-        PhotonResult response = getById(testDocId);
-        String classification = (String) response.get(Constants.CLASSIFICATION);
+        GetResponse response = getById(testDocId);
+        String classification = (String) response.getSource().get(Constants.CLASSIFICATION);
         assertEquals(classification, class_term);
 
         List<PhotonResult> result = search(class_term + " curli");
@@ -158,6 +160,7 @@ public class QueryByClassificationTest extends ESBaseTester {
             throw new RuntimeException(e);
         }
         try {
+            getServer().setMaxShards(null);
             getServer().updateIndexSettings(synonymPath.toString());
         } catch (IOException e) {
             throw new RuntimeException(e);
diff --git a/src/test/java/de/komoot/photon/query/QueryByLanguageTest.java b/src/test/java/de/komoot/photon/query/QueryByLanguageTest.java
index 5e43301..382a022 100644
--- a/src/test/java/de/komoot/photon/query/QueryByLanguageTest.java
+++ b/src/test/java/de/komoot/photon/query/QueryByLanguageTest.java
@@ -26,7 +26,7 @@ public class QueryByLanguageTest extends ESBaseTester {
 
     private Importer setup(String... languages) throws IOException {
         languageList = languages;
-        setUpES(dataDirectory, languages);
+        setUpES(languages);
         return makeImporterWithLanguages(languages);
     }
 
diff --git a/src/test/java/de/komoot/photon/query/QueryFilterTagValueTest.java b/src/test/java/de/komoot/photon/query/QueryFilterTagValueTest.java
index 0beec64..9d645d6 100644
--- a/src/test/java/de/komoot/photon/query/QueryFilterTagValueTest.java
+++ b/src/test/java/de/komoot/photon/query/QueryFilterTagValueTest.java
@@ -1,28 +1,24 @@
 package de.komoot.photon.query;
 
 import de.komoot.photon.ESBaseTester;
-import de.komoot.photon.Importer;
 import de.komoot.photon.PhotonDoc;
+import de.komoot.photon.Importer;
+
+import java.util.List;
+import java.util.stream.Stream;
+
 import de.komoot.photon.searcher.PhotonResult;
 import de.komoot.photon.searcher.TagFilter;
 import org.junit.jupiter.api.*;
-import org.junit.jupiter.api.io.TempDir;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.MethodSource;
 
-import java.nio.file.Path;
-import java.util.List;
-import java.util.stream.Stream;
-
 import static org.junit.jupiter.api.Assertions.*;
 import static org.junit.jupiter.params.provider.Arguments.arguments;
 
 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
 public class QueryFilterTagValueTest extends ESBaseTester {
-    @TempDir
-    private static Path instanceTestDirectory;
-
     private static final String[] TAGS = new String[]{"tourism", "attraction",
                                                       "tourism", "hotel",
                                                       "tourism", "museum",
@@ -35,7 +31,7 @@ public class QueryFilterTagValueTest extends ESBaseTester {
 
     @BeforeAll
     public void setUp() throws Exception {
-        setUpES(instanceTestDirectory, "en", "de", "fr");
+        setUpES();
         Importer instance = makeImporter();
         double lon = 13.38886;
         double lat = 52.51704;
@@ -58,7 +54,8 @@ public class QueryFilterTagValueTest extends ESBaseTester {
     @AfterAll
     @Override
     public void tearDown() {
-        super.tearDown();
+        deleteIndex();
+        shutdownES();
     }
 
     private List<PhotonResult> searchWithTags(String[] params) {
diff --git a/src/test/java/de/komoot/photon/searcher/GeocodeJsonFormatterTest.java b/src/test/java/de/komoot/photon/searcher/GeocodeJsonFormatterTest.java
new file mode 100644
index 0000000..ebca494
--- /dev/null
+++ b/src/test/java/de/komoot/photon/searcher/GeocodeJsonFormatterTest.java
@@ -0,0 +1,45 @@
+package de.komoot.photon.searcher;
+
+import de.komoot.photon.Constants;
+import org.json.JSONObject;
+import org.json.JSONArray;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class GeocodeJsonFormatterTest {
+
+    @Test
+    public void testConvertToGeojson() {
+        GeocodeJsonFormatter formatter = new GeocodeJsonFormatter(false, "en");
+        List<PhotonResult> allResults = new ArrayList<>();
+        allResults.add(createDummyResult("99999", "Park Foo", "leisure", "park"));
+        allResults.add(createDummyResult("88888", "Bar Park", "leisure", "park"));
+
+        String geojsonString = formatter.convert(allResults, null);
+        JSONObject jsonObj = new JSONObject(geojsonString);
+        assertEquals("FeatureCollection", jsonObj.getString("type"));
+        JSONArray features = jsonObj.getJSONArray("features");
+        assertEquals(2, features.length());
+        for (int i = 0; i < features.length(); i++) {
+            JSONObject feature = features.getJSONObject(i);
+            assertEquals("Feature", feature.getString("type"));
+            assertEquals("Point", feature.getJSONObject("geometry").getString("type"));
+            assertEquals("leisure", feature.getJSONObject("properties").getString(Constants.OSM_KEY));
+            assertEquals("park", feature.getJSONObject("properties").getString(Constants.OSM_VALUE));
+        }
+    }
+    
+    private PhotonResult createDummyResult(String postCode, String name, String osmKey,
+                    String osmValue) {
+        return new MockPhotonResult()
+                .put(Constants.POSTCODE, postCode)
+                .putLocalized(Constants.NAME, "en", name)
+                .put(Constants.OSM_KEY, osmKey)
+                .put(Constants.OSM_VALUE, osmValue);
+    }
+
+}
diff --git a/src/test/java/de/komoot/photon/searcher/StreetDupesRemoverTest.java b/src/test/java/de/komoot/photon/searcher/StreetDupesRemoverTest.java
index fc6fe8f..c5bcf22 100644
--- a/src/test/java/de/komoot/photon/searcher/StreetDupesRemoverTest.java
+++ b/src/test/java/de/komoot/photon/searcher/StreetDupesRemoverTest.java
@@ -1,6 +1,7 @@
 package de.komoot.photon.searcher;
 
 import de.komoot.photon.Constants;
+import org.json.JSONObject;
 import org.junit.jupiter.api.Test;
 
 import java.util.ArrayList;