Skip to content

Commit e7e3703

Browse files
authored
Merge pull request #1022 from lonvia/reverse-only
Add experimental reverse-only mode
2 parents f94de07 + 2e55434 commit e7e3703

File tree

9 files changed

+224
-106
lines changed

9 files changed

+224
-106
lines changed

src/main/java/de/komoot/photon/App.java

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -402,23 +402,25 @@ private static void startApi(ApiServerConfig args, Server server, @Nullable Nomi
402402

403403
photonServer.get("/status", new StatusRequestHandler(server));
404404

405-
photonServer.get("/api", new GenericSearchHandler<>(
406-
new SimpleSearchRequestFactory(
407-
dbProperties.getLanguages(),
408-
args.getDefaultLanguage(),
409-
args.getMaxResults(),
410-
dbProperties.getSupportGeometries()),
411-
server.createSearchHandler(args.getQueryTimeout()),
412-
formatter));
413-
414-
photonServer.get("/structured", new GenericSearchHandler<>(
415-
new StructuredSearchRequestFactory(
416-
dbProperties.getLanguages(),
417-
args.getDefaultLanguage(),
418-
args.getMaxResults(),
419-
dbProperties.getSupportGeometries()),
420-
server.createStructuredSearchHandler(args.getQueryTimeout()),
421-
formatter));
405+
if (!dbProperties.getReverseOnly()) {
406+
photonServer.get("/api", new GenericSearchHandler<>(
407+
new SimpleSearchRequestFactory(
408+
dbProperties.getLanguages(),
409+
args.getDefaultLanguage(),
410+
args.getMaxResults(),
411+
dbProperties.getSupportGeometries()),
412+
server.createSearchHandler(args.getQueryTimeout()),
413+
formatter));
414+
415+
photonServer.get("/structured", new GenericSearchHandler<>(
416+
new StructuredSearchRequestFactory(
417+
dbProperties.getLanguages(),
418+
args.getDefaultLanguage(),
419+
args.getMaxResults(),
420+
dbProperties.getSupportGeometries()),
421+
server.createStructuredSearchHandler(args.getQueryTimeout()),
422+
formatter));
423+
}
422424

423425
photonServer.get("/reverse", new GenericSearchHandler<>(
424426
new ReverseRequestFactory(

src/main/java/de/komoot/photon/DatabaseProperties.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public class DatabaseProperties {
2525
private boolean supportGeometries = false;
2626
private boolean synonymsInstalled = false;
2727
private ConfigExtraTags extraTags = new ConfigExtraTags();
28+
private boolean reverseOnly = false;
2829

2930
@SuppressWarnings("unused")
3031
public void setDatabaseVersion(String version) {
@@ -121,4 +122,12 @@ public String toString() {
121122
", extraTags=" + extraTags +
122123
'}';
123124
}
125+
126+
public void setReverseOnly(boolean reverseOnly) {
127+
this.reverseOnly = reverseOnly;
128+
}
129+
130+
public boolean getReverseOnly() {
131+
return reverseOnly;
132+
}
124133
}

src/main/java/de/komoot/photon/Server.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ public void recreateIndex(DatabaseProperties dbProperties) throws IOException {
140140

141141
new IndexSettingBuilder().setShards(5).createIndex(client, PhotonIndex.NAME);
142142

143-
new IndexMapping().putMapping(client, PhotonIndex.NAME);
143+
new IndexMapping(dbProperties.getReverseOnly()).putMapping(client, PhotonIndex.NAME);
144144

145145
saveToDatabase(dbProperties);
146146
}

src/main/java/de/komoot/photon/config/ImportFilterConfig.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ public class ImportFilterConfig {
3838
""")
3939
private boolean importGeometryColumn = false;
4040

41+
@Parameter(names = "-reverse-only", category = GROUP, description = """
42+
Set up database for reverse geocoding only""")
43+
private boolean reverseOnly = false;
44+
4145
public Set<String> getLanguages() {
4246
return new HashSet<>(languages);
4347
}
@@ -62,6 +66,7 @@ public DatabaseProperties getDatabaseProperties() {
6266
dbProps.setLanguages(getLanguages());
6367
}
6468
dbProps.setSupportGeometries(importGeometryColumn);
69+
dbProps.setReverseOnly(reverseOnly);
6570

6671
if (extraTags != null) {
6772
dbProps.setExtraTags(extraTags);

src/main/java/de/komoot/photon/opensearch/IndexMapping.java

Lines changed: 70 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ public class IndexMapping {
1717

1818
private PutMappingRequest.Builder mappings;
1919

20-
public IndexMapping() {
21-
setupBaseMappings();
20+
public IndexMapping(boolean reverseOnly) {
21+
setupBaseMappings(reverseOnly);
2222
}
2323

2424
public void putMapping(OpenSearchClient client, String indexName) throws IOException {
2525
client.indices().putMapping(mappings.index(indexName).build());
2626
}
2727

28-
private void setupBaseMappings() {
28+
private void setupBaseMappings(boolean reverseOnly) {
2929
mappings = new PutMappingRequest.Builder();
3030

3131
mappings.dynamic(DynamicMapping.False)
@@ -50,86 +50,89 @@ private void setupBaseMappings() {
5050
));
5151

5252
mappings.properties(DocFields.COORDINATE, b -> b.geoPoint(p -> p));
53-
mappings.properties(DocFields.COUNTRYCODE, b -> b.keyword(p -> p
54-
.index(true)
55-
.docValues(false)
56-
));
5753
mappings.properties(DocFields.IMPORTANCE, b -> b.float_(p -> p
5854
.index(false)
5955
));
6056

61-
mappings.properties(DocFields.HOUSENUMBER, b -> b.text(p -> p
62-
.index(true)
63-
.indexOptions(IndexOptions.Docs)
64-
.analyzer("index_housenumber")
65-
.searchAnalyzer("standard")
66-
.fields("full", f -> f.text(full -> full
67-
.index(true)
68-
.norms(false)
69-
.indexOptions(IndexOptions.Docs)
70-
.analyzer("lowercase_keyword")
71-
))
72-
));
73-
74-
mappings.properties(DocFields.POSTCODE, b -> b.text(p -> p
75-
.index(true)
76-
.norms(false)
77-
.analyzer("index_raw")
78-
));
57+
if (!reverseOnly) {
58+
mappings.properties(DocFields.COUNTRYCODE, b -> b.keyword(p -> p
59+
.index(true)
60+
.docValues(false)
61+
));
7962

80-
// General collectors.
81-
mappings.properties(DocFields.COLLECTOR + ".all", b -> b.text(p -> p
82-
.index(true)
83-
.norms(false)
84-
.indexOptions(IndexOptions.Freqs)
85-
.analyzer("index_fullword")
86-
.searchAnalyzer("search")
87-
.fields("ngram", ngramField -> ngramField.text(p1 -> p1
88-
.index(true)
89-
.norms(false)
90-
.indexOptions(IndexOptions.Freqs)
91-
.analyzer("index_ngram")
92-
.searchAnalyzer("search")
93-
))
94-
));
63+
mappings.properties(DocFields.HOUSENUMBER, b -> b.text(p -> p
64+
.index(true)
65+
.indexOptions(IndexOptions.Docs)
66+
.analyzer("index_housenumber")
67+
.searchAnalyzer("standard")
68+
.fields("full", f -> f.text(full -> full
69+
.index(true)
70+
.norms(false)
71+
.indexOptions(IndexOptions.Docs)
72+
.analyzer("lowercase_keyword")
73+
))
74+
));
9575

96-
mappings.properties(DocFields.COLLECTOR + ".name", b -> b.text(p -> p
97-
.index(true)
98-
.norms(false)
99-
.indexOptions(IndexOptions.Freqs)
100-
.analyzer("index_name_ngram")
101-
.searchAnalyzer("search")
102-
.fields("prefix", prefixField -> prefixField.text(p1 -> p1
103-
.index(true)
104-
.norms(false)
105-
.indexOptions(IndexOptions.Freqs)
106-
.analyzer("index_name_prefix")
107-
.searchAnalyzer("search_prefix")
108-
))
109-
));
76+
mappings.properties(DocFields.POSTCODE, b -> b.text(p -> p
77+
.index(true)
78+
.norms(false)
79+
.analyzer("index_raw")
80+
));
11081

111-
mappings.properties(DocFields.COLLECTOR + ".parent", b -> b.text(p -> p
112-
.index(true)
113-
.norms(false)
114-
.indexOptions(IndexOptions.Docs)
115-
.analyzer("index_name_ngram")
116-
.searchAnalyzer("search")
117-
));
82+
// General collectors.
83+
mappings.properties(DocFields.COLLECTOR + ".all", b -> b.text(p -> p
84+
.index(true)
85+
.norms(false)
86+
.indexOptions(IndexOptions.Freqs)
87+
.analyzer("index_fullword")
88+
.searchAnalyzer("search")
89+
.fields("ngram", ngramField -> ngramField.text(p1 -> p1
90+
.index(true)
91+
.norms(false)
92+
.indexOptions(IndexOptions.Freqs)
93+
.analyzer("index_ngram")
94+
.searchAnalyzer("search")
95+
))
96+
));
11897

119-
for (var field : ADDRESS_FIELDS) {
120-
mappings.properties(DocFields.COLLECTOR + ".field." + field, b -> b.text(p -> p
98+
mappings.properties(DocFields.COLLECTOR + ".name", b -> b.text(p -> p
12199
.index(true)
122100
.norms(false)
123-
.analyzer("index_raw")
101+
.indexOptions(IndexOptions.Freqs)
102+
.analyzer("index_name_ngram")
124103
.searchAnalyzer("search")
125-
.fields("full", prefixField -> prefixField.text(p1 -> p1
104+
.fields("prefix", prefixField -> prefixField.text(p1 -> p1
126105
.index(true)
127106
.norms(false)
128-
.indexOptions(IndexOptions.Docs)
129-
.analyzer("index_name_full")
107+
.indexOptions(IndexOptions.Freqs)
108+
.analyzer("index_name_prefix")
130109
.searchAnalyzer("search_prefix")
131110
))
132111
));
112+
113+
mappings.properties(DocFields.COLLECTOR + ".parent", b -> b.text(p -> p
114+
.index(true)
115+
.norms(false)
116+
.indexOptions(IndexOptions.Docs)
117+
.analyzer("index_name_ngram")
118+
.searchAnalyzer("search")
119+
));
120+
121+
for (var field : ADDRESS_FIELDS) {
122+
mappings.properties(DocFields.COLLECTOR + ".field." + field, b -> b.text(p -> p
123+
.index(true)
124+
.norms(false)
125+
.analyzer("index_raw")
126+
.searchAnalyzer("search")
127+
.fields("full", prefixField -> prefixField.text(p1 -> p1
128+
.index(true)
129+
.norms(false)
130+
.indexOptions(IndexOptions.Docs)
131+
.analyzer("index_name_full")
132+
.searchAnalyzer("search_prefix")
133+
))
134+
));
135+
}
133136
}
134137
}
135138
}

src/test/java/de/komoot/photon/api/ApiBaseTester.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import java.util.stream.Collectors;
1414
import java.util.stream.Stream;
1515

16-
import static org.assertj.core.api.Assertions.assertThatIOException;
16+
import static org.assertj.core.api.Assertions.*;
1717

1818
public class ApiBaseTester extends ESBaseTester {
1919
private static final int LISTEN_PORT = 30234;
@@ -49,10 +49,12 @@ protected String readURL(String url) throws IOException {
4949
.lines().collect(Collectors.joining("\n"));
5050
}
5151

52-
protected void assertHttpError(String url, int expectedCode) {
53-
assertThatIOException()
54-
.isThrownBy(() -> readURL(url))
55-
.withMessageContaining("response code: " + expectedCode);
56-
52+
protected void assertHttpResponseCode(String url, int expectedCode) {
53+
try {
54+
assertThat(connect(url))
55+
.hasFieldOrPropertyWithValue("responseCode", expectedCode);
56+
} catch (IOException e) {
57+
throw new RuntimeException(e);
58+
}
5759
}
5860
}

src/test/java/de/komoot/photon/api/ApiIntegrationTest.java

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import java.util.List;
1818

1919
import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson;
20-
import static org.junit.jupiter.api.Assertions.assertEquals;
2120

2221
/**
2322
* API tests that check queries against an already running ES instance and
@@ -77,7 +76,7 @@ public void tearDown() {
7776
@ParameterizedTest
7877
@FieldSource("BASE_URLS")
7978
void testBogus(String baseUrl) {
80-
assertHttpError(baseUrl + "&bogus=thing", 400);
79+
assertHttpResponseCode(baseUrl + "&bogus=thing", 400);
8180
}
8281

8382
@ParameterizedTest
@@ -167,7 +166,7 @@ void testLimitParameter(String baseUrl) throws Exception {
167166
@ParameterizedTest
168167
@FieldSource("BASE_URLS")
169168
void testBadLimitParameter(String baseUrl) {
170-
assertHttpError(baseUrl + "&limit=NaN", 400);
169+
assertHttpResponseCode(baseUrl + "&limit=NaN", 400);
171170
}
172171

173172
@ParameterizedTest
@@ -198,7 +197,7 @@ void testManyLayers(String baseUrl) throws Exception {
198197
@ParameterizedTest
199198
@FieldSource("BASE_URLS")
200199
void testBadLayerParameter(String baseUrl) {
201-
assertHttpError(baseUrl + "&layer=locality&layer=suburb", 400);
200+
assertHttpResponseCode(baseUrl + "&layer=locality&layer=suburb", 400);
202201
}
203202

204203
@ParameterizedTest
@@ -265,7 +264,7 @@ void testOsmTagFilterNeg(String baseUrl) throws Exception {
265264
@ParameterizedTest
266265
@FieldSource("BASE_URLS")
267266
void testBadOsmTagParameter(String baseUrl) {
268-
assertHttpError(baseUrl + "&osm_tag=bad:bad:bad", 400);
267+
assertHttpResponseCode(baseUrl + "&osm_tag=bad:bad:bad", 400);
269268
}
270269

271270
@ParameterizedTest
@@ -291,7 +290,7 @@ void testExcludeCategory(String baseUrl) throws Exception {
291290
@ParameterizedTest
292291
@ValueSource(strings = {"4+5.6", "abc", "ab..23", "a.b,c", "a.b,!c.d"})
293292
void testCategoryBadValues(String paramValue) {
294-
assertHttpError("/api?q=berlin&include=" + paramValue, 400);
293+
assertHttpResponseCode("/api?q=berlin&include=" + paramValue, 400);
295294
}
296295

297296
@ParameterizedTest
@@ -306,18 +305,18 @@ void testCategoryBadValues(String paramValue) {
306305
"lat=52.54714&lon=-180.01", "lat=-90.01&lon=13.39026"
307306
})
308307
void testReverseBadLocation(String param) {
309-
assertHttpError("/reverse?" + param, 400);
308+
assertHttpResponseCode("/reverse?" + param, 400);
310309
}
311310

312311
@ParameterizedTest
313312
@ValueSource(strings = {"bad", "NaN", "0.0", "-10.0"})
314313
void testReverseBadRadius(String param) {
315-
assertHttpError("/reverse?lat=52.54714&lon=13.39026&radius=" + param, 400);
314+
assertHttpResponseCode("/reverse?lat=52.54714&lon=13.39026&radius=" + param, 400);
316315
}
317316

318317
@Test
319318
void testSearchMissingQuery() {
320-
assertHttpError("/api?debug=1", 400);
319+
assertHttpResponseCode("/api?debug=1", 400);
321320
}
322321

323322
@Test
@@ -341,7 +340,7 @@ void testEmptyQueryWithInclude() throws Exception {
341340
"lat=52.54714&lon=-180.01", "lat=-90.01&lon=13.39026"
342341
})
343342
void testSearchBadLocation(String param) {
344-
assertHttpError("/api?q=berlin&" + param, 400);
343+
assertHttpResponseCode("/api?q=berlin&" + param, 400);
345344
}
346345

347346
@ParameterizedTest
@@ -352,18 +351,18 @@ void testSearchBadLocation(String param) {
352351
"-181, 9, 4, 12", "12, 9, 181, 12"
353352
})
354353
void testSearchBadBbox(String param) {
355-
assertHttpError("/api?q=berlin&bbox=" + param, 400);
354+
assertHttpResponseCode("/api?q=berlin&bbox=" + param, 400);
356355
}
357356

358357

359358
@ParameterizedTest
360359
@ValueSource(strings = {"bad", "NaN"})
361360
void testSearchBadLocationBiasScale(String param) {
362-
assertHttpError("/api?q=berlin&lat=52.54714&lon=13.39026&location_bias_scale=" + param, 400);
361+
assertHttpResponseCode("/api?q=berlin&lat=52.54714&lon=13.39026&location_bias_scale=" + param, 400);
363362
}
364363

365364
@Test
366-
void testMetricsEndpoint() throws IOException {
367-
assertEquals(200, connect("/metrics").getResponseCode());
365+
void testMetricsEndpoint() {
366+
assertHttpResponseCode("/metrics", 200);
368367
}
369368
}

0 commit comments

Comments
 (0)