Skip to content

Commit

Permalink
feat: use separated county search in place search
Browse files Browse the repository at this point in the history
  • Loading branch information
amoncaldas committed Sep 23, 2021
1 parent fe88dce commit fd5f3e9
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 24 deletions.
8 changes: 4 additions & 4 deletions docs/search-results-criteria.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,14 @@ As the `geocode/search` does not accept a parameter for layer priorities, or the
the current implementation creates results by doing three searches:

1. A search for items in the `locality` layer, passing a focus point
1. A search for items in the other layers, except `locality` and `venue`
1. A search for items in the `county` layer, passing a focus point
1. A search for items in the other layers, except `locality`, `county` and `venue`
1. A search for items in the `venue` layer, that are within the current map view bounds

Having the results of the three searches, the app merges them using the following rules:

- If there are results for `locality` layer they will fill 20% of the slots (in case of 10 will fill 2 slots)
- If there are results for all the layers except `locality` and `venue` they will fill 40% of the slots
- If there are results for `venue` layers they will fill the missing 40% of the slots
- If there are results for `locality` and `county` layers, they will fill the initial slots
- If there are results for all the layers except `locality`, `county` they will fill the other available slots

Important: *If some searches do not bring results, the empty slots are filled with extra items from the other searches*

Expand Down
2 changes: 1 addition & 1 deletion src/fragments/forms/place-input/PlaceInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@
<v-list-tile @click.stop="selectSuggestion(placeSuggested)" :key="placeSuggested.id" v-for='placeSuggested in placeSuggestions'
:title="placeSuggested.placeName.trim()">
<v-list-tile-action class="hidden-sm-and-down">
<v-icon v-if="placeSuggested.properties.layer === 'locality' || placeSuggested.properties.layer === 'city'">location_city</v-icon>
<v-icon v-if="placeSuggested.properties.layer === 'locality' || placeSuggested.properties.layer === 'city' || placeSuggested.properties.layer === 'county'">location_city</v-icon>
<img width="25px" v-else-if="showAreaIcon(placeSuggested)" src="@/assets/img/country-icon.png" height="auto" />
<v-icon v-else>place</v-icon>
</v-list-tile-action>
Expand Down
57 changes: 46 additions & 11 deletions src/support/admin-area-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,13 @@ class AdminAreaLoader {
adminAreaFilter.state = place.properties.region.toLowerCase().replace(' region', '')
}
if (place.properties.county) {
let county = place.properties.county.toLowerCase().replace(' county', '')
adminAreaFilter.county = county
adminAreaFilter.county = place.properties.county.toLowerCase().replace(' county', '')
} else {
if (place.placeName.indexOf(',') > -1) {
adminAreaFilter.county = place.placeName.split(',')[0]
} else {
adminAreaFilter.county = place.placeName
}
}
}
if (layer === 'locality') {
Expand All @@ -34,6 +39,12 @@ class AdminAreaLoader {
let locality = place.properties.locality || place.properties.county || place.properties.macrocounty
if (locality) {
adminAreaFilter.city = locality.toLowerCase()
} else {
if (place.placeName.indexOf(',') > -1) {
adminAreaFilter.city = place.placeName.split(',')[0]
} else {
adminAreaFilter.city = place.placeName
}
}
}
return adminAreaFilter
Expand All @@ -59,25 +70,49 @@ class AdminAreaLoader {
let layerZoom = GeoUtils.zoomLevelByLayer(layer)

let context = this
place.resolve(layerZoom).then(() => {
let adminAreaFilter = context.buildAdminAreaFilter(place, layer)
NominatimService.query(adminAreaFilter).then((response) => {
let validPolygons = context.adjustAdminArea(place, response.data)
if (validPolygons) {
if (place.isEmpty()) {
place.resolve(layerZoom).then(() => {
context.getPlaceValidPolygons(place, layer).then((validPolygons) => {
resolve(validPolygons)
} else {
resolve([])
}
}).catch(err => {
reject(err)
})
})
} else {
context.getPlaceValidPolygons(place, layer).then((validPolygons) => {
resolve(validPolygons)
}).catch(err => {
reject(err)
})
})
}
} else {
resolve([])
}
})
}

/**
* Get place valid polygons
* @param {Place} place
* @param {String} layer
* @returns {Array}
*/
getPlaceValidPolygons (place, layer) {
return new Promise((resolve, reject) => {
let adminAreaFilter = this.buildAdminAreaFilter(place, layer)
NominatimService.query(adminAreaFilter).then((response) => {
let validPolygons = this.adjustAdminArea(place, response.data)
if (validPolygons) {
resolve(validPolygons)
} else {
resolve([])
}
}).catch(err => {
reject(err)
})
})
}

/**
* check if a Place is inside of any of the polygons passed
* @param {*} polygons
Expand Down
31 changes: 23 additions & 8 deletions src/support/ors-api-runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,17 @@ const PlacesSearch = (term, quantity = 100, restrictArea = true) => {
promises.push(client.geocode(localityArgs))
AppLoader.getInstance().appHooks.run('placeSearchLocalityArgsDefined', localityArgs)

// Build a search counties only
let countyArgs = OrsParamsParser.buildPlaceSearchArgs(term, false)
countyArgs.size = 2
countyArgs.layers = ['county']
promises.push(client.geocode(countyArgs))
AppLoader.getInstance().appHooks.run('placeSearchCountyArgsDefined', countyArgs)

// Build a search for addresses
let addressesArgs = OrsParamsParser.buildPlaceSearchArgs(term, false)
addressesArgs.size = quantity
addressesArgs.layers = ['country', 'region', 'macrocounty', 'borough', 'macroregion', 'county', 'neighbourhood', 'borough', 'street', 'address', 'coarse'] // `coarse` will bring places by postal code
addressesArgs.layers = ['country', 'region', 'macrocounty', 'macroregion', 'neighbourhood', 'borough', 'street', 'address', 'coarse'] // `coarse` will bring places by postal code
promises.push(client.geocode(addressesArgs))
AppLoader.getInstance().appHooks.run('placeSearchAddressArgsDefined', addressesArgs)

Expand Down Expand Up @@ -170,19 +177,22 @@ const buildPlacesSearchResult = (responses, quantity) => {
quantity = quantity - localityFeatures.length
features = features.concat(localityFeatures)
}

let countyFeatures = responses[1].features
if(countyFeatures && countyFeatures.length > 0) {
quantity = quantity - countyFeatures.length
features = features.concat(countyFeatures)
}

// By default, get all the features of the administrative places list
let adminFeatures = []
if (responses.length > 1) {
adminFeatures = responses[1].features
if (adminFeatures.length > 0) {
adminFeatures[0].bestMatch = true
}
adminFeatures = responses[2].features
}

// If there are administrative places and also places
// from POIs (venues) then merge them into the collection
let poisFeatures = responses.length === 3 ? responses[2].features : []
let poisFeatures = responses.length === 4 ? responses[3].features : []

if (poisFeatures.length > 0) {
let half = Math.round((quantity / 2))
Expand Down Expand Up @@ -225,15 +235,20 @@ const sortFeatures = (features) => {
// Move best match to to first position (duplicated items will be removed later)
features.splice(0, 0, features[bestMatchIndex])
}
let closestCityIndex = lodash.findIndex(features, function(f) { return f.properties.layer === 'locality' || f.properties.layer === 'city' })
let closestCityIndex = lodash.findIndex(features, function(f) { return f.properties.layer === 'locality' || f.properties.layer === 'city'})
if (closestCityIndex > 1) {
// Move closest city to second position (duplicated items will be removed later)
features.splice(1, 0, features[closestCityIndex])
}
let closestCountyIndex = lodash.findIndex(features, function(f) { return f.properties.layer === 'county' })
if (closestCountyIndex > 1) {
// Move closest city to second position (duplicated items will be removed later)
features.splice(2, 0, features[closestCountyIndex])
}
let closestCountryIndex = lodash.findIndex(features, function(f) { return f.properties.layer === 'country'})
if (closestCountryIndex > 2) {
// Move closest city to third position (duplicated items will be removed later)
features.splice(2, 0, features[closestCountryIndex])
features.splice(3, 0, features[closestCountryIndex])
}
// remove duplicated
features = lodash.uniqBy(features, function (f) { return f.properties.unique_id })
Expand Down

0 comments on commit fd5f3e9

Please sign in to comment.