Skip to content
This repository has been archived by the owner on Feb 2, 2023. It is now read-only.

Commit

Permalink
feat(ranking-info): expose and explain _rankingInfo (#628)
Browse files Browse the repository at this point in the history
* feat(rankingInfo): allow places.js to use getRankingInfo

* doc(rankingInfo): document how getRankingInfo and _rankingInfo work with Places

* doc(ranking-info): add administrative in the example

* doc(ranking-info): document _rankingInfo attribute in the REST API

* doc(ranking-info): add `centroid` doc

* doc(ranking-info): add test

* doc(ranking-info): add link to the beta program form
  • Loading branch information
JonathanMontane authored and raphi committed Nov 1, 2018
1 parent ff084c3 commit 131123f
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 2 deletions.
12 changes: 12 additions & 0 deletions docs/source/api-clients.html.md.erb
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,18 @@ Radius in meters to search around the latitude/longitude. Otherwise a default ra
given the area density.
</td>
</tr>
<tr>
<td markdown="1">
<div class="api-entry" id="api-options-getRankingInfo"><code>getRankingInfo</code></div>

Type: **boolean**
</td>
<td markdown="1">
Controls whether the [_rankingInfo](https://www.algolia.com/doc/api-reference/api-methods/search/#method-response-_rankinginfo) object should be included in the hits. This defaults to `false`.

The _rankingInfo object for a Places query is slightly different from a regular Algolia query and you can read up more about the difference and how to leverage them in [our guide](examples.html#using-_rankinginfo).
</td>
</tr>
</tbody>
</table>

Expand Down
12 changes: 12 additions & 0 deletions docs/source/documentation.html.md.erb
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,18 @@ Filters the results inside the area defined by a shape. [See guide](https://www.

Format: `p1Lat, p1Lng, p2Lat, p2Lng, p3Lat, p3Lng...`
</td>
</tr>
<tr>
<td markdown="1">
<div class="api-entry" id="api-options-getRankingInfo"><code>getRankingInfo</code></div>

Type: **boolean**
</td>
<td markdown="1">
Controls whether the [_rankingInfo](https://www.algolia.com/doc/api-reference/api-methods/search/#method-response-_rankinginfo) object should be included in the hits. This defaults to `false`.

The _rankingInfo object for a Places query is slightly different from a regular Algolia query and you can read up more about the difference and how to leverage them in [our guide](examples.html#using-_rankinginfo).
</td>
</tr>
</tbody>
</table>
Expand Down
54 changes: 52 additions & 2 deletions docs/source/examples.html.md.erb
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Then use this:

### Templates

**Warning:** This is an advanced feature.
**Warning:** This is an advanced feature.

Although Places.js comes with a good default template that should fit most use cases, you may want to customize both the input value and dropdown suggestion templates to better fit your needs.

Expand Down Expand Up @@ -210,4 +210,54 @@ In this section, we will see how you can do _emulate_ reverse geocoding to find

**Note:** This example uses the standard [JavaScript API client](https:/algolia/algoliasearch-client-javascript) in which the Places API is integrated. This example does not use the Places.js library.

**Note:** This is not a reverse geocoding API, and it is still bound by the ranking used for search, which means that in some cases large close-by cities can be promoted over a more closely located city.
**Note:** This is not a reverse geocoding API, and it is still bound by the ranking used for search, which means that in some cases large close-by cities can be promoted over a more closely located city.

### Using _rankingInfo

**Concepts:** _rankingInfo, query strategy, geolocation precision.

In this section, we will see how we can leverage `_rankingInfo` to provide additional information to our user about certain behaviours of the query strategy.

As with any Algolia query, `_rankingInfo` will include information about how the ranking was computed based on the `words`, `exact`, `filters`, `nbTypos`, etc.
However, Places also enriches the _rankingInfo with additional information based on which part of the query strategy was used to return this result.
Finally, in countries where Places supports house level precision queries, it also provides some data on how precise the geolocation resolution was.

As such, on top of the regular `_rankingInfo` fields, Places exposes the two following:
- query
- roadNumberPrecision

##### query
The `query` field of the `_rankingInfo` object is a reference to which query strategy was used to find this result while executing the Algolia Places Query.
You can read more about the Algolia Places query strategy [here](api-clients#query-strategy).

It can take 3 values depending of the strategy used to find this record:
- **worldwide_query**: Places searched the entire world to find this record.
- **local_query**: Places searched the country of the user to find this record.
- **geo_query**: Places searched around the user to find this record.

You can leverage this attribute to better understand how your constraints impact the relevance of your search.

**Note:** This is a very advanced feature, which will be irrelevant to most users.

**Note:** All searches that Places does internally still take into account the filters that you applied, so if you restrict a query to only a few countries, a worldwide query will only look into these few countries.

##### roadNumberPrecision
The `roadNumberPrecision` field of the `_rankingInfo` object provides additional information on how precise the geolocation of the record is.

By default, Places only offers precision up to the street level, which means that all the house numbers of a street will have the same geolocation. However, Places offers house level precision in France, if you are part of [the opt-in beta for this program](https://goo.gl/forms/8sIEGSShUm85jMLp2).
In this case, the `roadNumberPrecision` field will return either:
- **exact**: the house number passed in the query was found exactly in the data
- **closest**: interpolate the position based on known datapoints
- **centroid**: computed center of mass of the geometric area

##### Demo
In this demo, we will visually show which query strategy was used to find each suggestion (on the left of the suggestion), as well as show the geolocation precision of results on the right.
Remember that house level precision is only available in France, so here are some example queries that you can try to see how things work under the hood:
- `L` (or any first letter that is not the first letter of a large city that is close to you)
- `55 rue d'Amsterdam, Paris` (look at how there are 2 records and only one has the exact house number - 3 circles vs 2 circles)

<%= partial '/partials/examples/ranking_info', locals: config[:credentials][:documentation] %>

```html
<%= partial '/partials/examples/ranking_info', locals: config[:credentials][:placeholder] %>
```
119 changes: 119 additions & 0 deletions docs/source/partials/examples/_ranking_info.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<input type="search" id="ranking-info" class="form-control" placeholder="Where are we going?" />

<%= javascript_include_tag config[:places_lib_url] %>
<style>
.suggestion {
display: flex;
flex-direction: row;
box-sizing: border-box;
align-items: center;
width: 100%;
padding-right: 18px;
}

.suggestion-icon {
width: 20px;
height: 20px;
margin-right: 8px;
flex-shrink: 0;
display: flex;
align-items: center;
opacity: 0.2;
}

.suggestion-name {
margin-left: 4px;
margin-right: 4px;
flex-grow: 0;
flex-shrink: 0;
}

.suggestion-address {
flex-grow: 1;
flex-shrink: 1;
margin-right: 8px;
font-size: 0.8em;
color: rgba(74, 74, 76, 0.5);
}

.suggestion-precision {
width: 20px;
height: 20px;
margin-left: 8px;
flex-shrink: 0;
display: flex;
align-items: center;
animation: none;
}
</style>
<script>
(function() {
const formatIcon = (query) => {
switch (query) {
case "worldwide_query":
// globe icon - result found while searching in the whole world (still respects filter restrictions)
return `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"><path d="M10 0C4.48 0 0 4.48 0 10s4.48 10 10 10 10-4.48 10-10S15.52 0 10 0zM9 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L7 13v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H6V8h2c.55 0 1-.45 1-1V5h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"/></svg>`
case "local_query":
// building icon - result found while searching in the country of the user (still respects filter restrictions)
return `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24"><path d="M12 .6L2.5 6.9h18.9L12 .6zM3.8 8.2c-.7 0-1.3.6-1.3 1.3v8.8L.3 22.1c-.2.3-.3.5-.3.6 0 .6.8.6 1.3.6h21.5c.4 0 1.3 0 1.3-.6 0-.2-.1-.3-.3-.6l-2.2-3.8V9.5c0-.7-.6-1.3-1.3-1.3H3.8zm2.5 2.5c.7 0 1.1.6 1.3 1.3v7.6H5.1V12c0-.7.5-1.3 1.2-1.3zm5.7 0c.7 0 1.3.6 1.3 1.3v7.6h-2.5V12c-.1-.7.5-1.3 1.2-1.3zm5.7 0c.7 0 1.3.6 1.3 1.3v7.6h-2.5V12c-.1-.7.5-1.3 1.2-1.3z"/></svg>`
case "geo_query":
// pin icon - result found while searching near location of the user (still respects filter restrictions)
return `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 14 20"><path d="M7 0C3.13 0 0 3.13 0 7c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5C5.62 9.5 4.5 8.38 4.5 7S5.62 4.5 7 4.5 9.5 5.62 9.5 7 8.38 9.5 7 9.5z"/></svg>`
default:
return ``;
}
}

const formatName = ({ name }) => name
const formatAddress = ({ suburb, city, postcode, administrative, country }) => {
return [ suburb, city, postcode, administrative, country ]
.filter(v => !!v)
.join(', ')
}

const formatPrecision = (type, roadNumberPrecision) => {
if (type === 'city') {
// 0 circle - city level precision
return ``;
}

switch (roadNumberPrecision) {
case "exact":
// 3 circles - house level precision
return `<svg width="20" height="20" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<circle r="12" cy="16" cx="16" fill="#ddd"/>
<circle r="8" cy="16" cx="16" fill="#aaa"/>
<circle r="4" cy="16" cx="16" fill="#000"/>
</svg>`;
case "closest":
// 2 circles - house number not found - returned geolocation of the closest house number.
return `<svg width="20" height="20" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<circle r="12" cy="16" cx="16" fill="#ddd"/>
<circle r="8" cy="16" cx="16" fill="#aaa"/>
</svg>`;
default:
// 1 circle - street level precision
return `<svg width="20" height="20" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<circle r="12" cy="16" cx="16" fill="#ddd"/>
</svg>`;
}
}

const formatSuggestion = ({ highlight, hit: { _rankingInfo }, type }) => `<div class="suggestion">
<span class="suggestion-icon">${formatIcon(_rankingInfo.query)}</span>
<span class="suggestion-name">${formatName(highlight)}</span>
<span class="suggestion-address">${formatAddress(highlight)}</span>
<span class="suggestion-precision">${formatPrecision(type, _rankingInfo.roadNumberPrecision)}</span>
</div>`;

const placesAutocomplete = places({
appId: '<%= app_id %>',
apiKey: '<%= api_key %>',
getRankingInfo: true,
container: document.querySelector('#ranking-info'),
templates: {
suggestion: formatSuggestion
}
});
})();
</script>
5 changes: 5 additions & 0 deletions src/createAutocompleteSource.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export default function createAutocompleteSource({
aroundLatLngViaIP,
insideBoundingBox,
insidePolygon,
getRankingInfo,
countries,
formatInputValue,
computeQueryParams = params => params,
Expand Down Expand Up @@ -62,6 +63,10 @@ export default function createAutocompleteSource({
defaultQueryParams.insidePolygon = insidePolygon;
}

if (getRankingInfo) {
defaultQueryParams.getRankingInfo = getRankingInfo;
}

let userCoords;
if (useDeviceLocation) {
navigator.geolocation.watchPosition(({ coords }) => {
Expand Down
9 changes: 9 additions & 0 deletions src/createAutocompleteSource.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,15 @@ describe('createAutocompleteSource', () => {
});
});

it('supports getRankingInfo option', () => {
const { source, defaults } = setup({ getRankingInfo: true });
source(defaults.query);
expect(algoliasearch.__searchSpy).toHaveBeenCalledWith({
...defaults,
getRankingInfo: true,
});
});

it('supports hitsPerPage option', () => {
const { source, defaults } = setup({ hitsPerPage: 2 });
source(defaults.query);
Expand Down

0 comments on commit 131123f

Please sign in to comment.