Skip to content

Commit 757fa22

Browse files
Merge pull request #1 from milan-fabian/feature/area-filter
Added support for searching by administration area or country
2 parents f714ed4 + e69516a commit 757fa22

2 files changed

Lines changed: 30 additions & 3 deletions

File tree

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ systemctl start geocoding-api.service
3434
systemctl status geocoding-api.service
3535
```
3636

37-
Additionally, nginx proxy should be used
37+
Geonames data are parsed and processed during the first start, which requires some times and memor. At least 6GB RAM is required and it takes about 25 minutes on a CPU with 2 Skylake cores. Database loading takes about 5 minutes after that.
38+
39+
Additionally, nginx proxy should be used.
3840

3941
## Terms & Privacy
4042
Open-Meteo APIs are free for open-source developer and non-commercial use. We do not restrict access, but ask for fair use.

Sources/App/GeocodingapiController.swift

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,24 @@ struct GeocodingapiController: RouteCollection {
5555
let language = params.language ?? "en"
5656
let languageId = database.geonames.languages.firstIndex(of: language) ?? database.geonames.languages.firstIndex(of: "en")!
5757
let count = try params.getCount()
58-
59-
var results = params.name.count < 2 ? [] : database.search(params.name, languageId: Int32(languageId), maxCount: count)
58+
59+
var name = params.name
60+
var areaIds: [Int32]?
61+
if name.contains(",") { // Split string by comma, so we can filter the results later by second part
62+
let parts = name.components(separatedBy: ",")
63+
name = parts[0].trimmingCharacters(in: .whitespacesAndNewlines)
64+
let areaName = parts[1].trimmingCharacters(in: .whitespacesAndNewlines)
65+
if areaName.count > 1 {
66+
areaIds = database.search(areaName, languageId: Int32(languageId), maxCount: 10).compactMap({
67+
guard ["ADM1","ADM2","ADM3","ADM4","PCLI"].contains(database.geonames.geonames[$0.0]?.featureCode) else {
68+
return nil
69+
}
70+
return $0.0
71+
})
72+
}
73+
}
74+
75+
var results = params.name.count < 2 ? [] : database.search(name, languageId: Int32(languageId), maxCount: count)
6076
/// TODO country filter need to be inside database match, because `count` would be wrong otherwise
6177
if let countryCode = params.countryCode {
6278
/*guard let countryId = searchTree.geonames.countryIso2.firstIndex(of: countryCode) else {
@@ -69,6 +85,15 @@ struct GeocodingapiController: RouteCollection {
6985
return c == countryCode
7086
})
7187
}
88+
if let areas = areaIds {
89+
results = results.filter({ // Filter the results by second part of the original string
90+
return areas.contains(database.geonames.geonames[$0.0]?.admin1ID ?? -1)
91+
|| areas.contains(database.geonames.geonames[$0.0]?.admin2ID ?? -1)
92+
|| areas.contains(database.geonames.geonames[$0.0]?.admin3ID ?? -1)
93+
|| areas.contains(database.geonames.geonames[$0.0]?.admin4ID ?? -1)
94+
|| areas.contains(database.geonames.geonames[$0.0]?.countryID ?? -1)
95+
})
96+
}
7297
let mapped: [GeocodingApi.Geoname] = results.map({
7398
guard let geoname = database.geonames.getResponse(id: $0.0, languageId: Int32(languageId), searchRank: $0.1) else {
7499
fatalError("Geoname in search index was not in database.")

0 commit comments

Comments
 (0)