Open bidoubiwa opened 3 years ago
These are the tests that should be working when proximityGeoRule
is set to true
// geo-rules.tests.ts
import { adaptGeoPointsRules } from '../geo-rules-adapter'
test('Adapt geoPoints rules without a boundingBox', () => {
const rules = adaptGeoPointsRules()
expect(rules).toBeUndefined()
})
test('Adapt geoPoints rules with same 0 lat and 0 lng geo points', () => {
const rules = adaptGeoPointsRules({
insideBoundingBox: '0,0,0,0',
})
expect(rules?.filter).toBe('_geoRadius(0, 0, 0)')
expect(rules?.sort).toBe('_geoPoint(0, 0):asc')
})
test('Adapt geoPoints rules with integer geo points', () => {
const rules = adaptGeoPointsRules({
insideBoundingBox: '1,2,3,4',
})
expect(rules?.filter).toBe(
'_geoRadius(2.0003044085023727, 2.999390393801055, 157201.5)'
)
expect(rules?.sort).toBe(
'_geoPoint(2.0003044085023727, 2.999390393801055):asc'
)
})
test('Try geoContext with only a radius', () => {
const rules = adaptGeoPointsRules({
aroundRadius: 1,
})
expect(rules).toBeUndefined()
})
test('Try geoContext with an aroundLatLng', () => {
const rules = adaptGeoPointsRules({
aroundLatLng: '51.1241999, 9.662499900000057',
})
expect(rules?.sort).toBe('_geoPoint(51.1241999, 9.662499900000057):asc')
expect(rules?.filter).toBeUndefined()
})
test('Try geoContext with an aroundLatLng and a radius', () => {
const rules = adaptGeoPointsRules({
aroundLatLng: '51.1241999, 9.662499900000057',
aroundRadius: 1,
})
expect(rules?.sort).toBe('_geoPoint(51.1241999, 9.662499900000057):asc')
expect(rules?.filter).toBe('_geoRadius(51.1241999, 9.662499900000057, 1)')
})
test('Try geoContext with an aroundLatLng and a 0 radius', () => {
const rules = adaptGeoPointsRules({
aroundLatLng: '51.1241999, 9.662499900000057',
aroundRadius: 0,
})
expect(rules?.sort).toBe('_geoPoint(51.1241999, 9.662499900000057):asc')
expect(rules?.filter).toBe('_geoRadius(51.1241999, 9.662499900000057, 0)')
})
test('Try geoContext with aroundLatLng, radius and insideBoundingBox', () => {
const rules = adaptGeoPointsRules({
aroundLatLng: '51.1241999, 9.662499900000057',
aroundRadius: 1,
insideBoundingBox: '1,2,3,4',
})
expect(rules?.filter).toBe(
'_geoRadius(2.0003044085023727, 2.999390393801055, 157201.5)'
)
expect(rules?.sort).toBe(
'_geoPoint(2.0003044085023727, 2.999390393801055):asc'
)
})
test('Try geoContext with a radius and insideBoundingBox', () => {
const rules = adaptGeoPointsRules({
aroundRadius: 1,
insideBoundingBox: '1,2,3,4',
})
expect(rules?.filter).toBe(
'_geoRadius(2.0003044085023727, 2.999390393801055, 157201.5)'
)
expect(rules?.sort).toBe(
'_geoPoint(2.0003044085023727, 2.999390393801055):asc'
)
})
test('Try geoContext with aroundLatLng and insideBoundingBox', () => {
const rules = adaptGeoPointsRules({
aroundLatLng: '51.1241999, 9.662499900000057',
insideBoundingBox: '1,2,3,4',
})
expect(rules?.filter).toBe(
'_geoRadius(2.0003044085023727, 2.999390393801055, 157201.5)'
)
expect(rules?.sort).toBe(
'_geoPoint(2.0003044085023727, 2.999390393801055):asc'
)
})
They should also pass the following tests in search-params.tests.ts
import { adaptSearchParams } from '../search-params-adapter'
test('Adapt basic SearchContext ', () => {
const searchParams = adaptSearchParams({
indexUid: 'test',
paginationTotalHits: 20,
})
expect(searchParams.attributesToHighlight).toContain('*')
expect(searchParams.attributesToHighlight?.length).toBe(1)
})
test('Adapt SearchContext with filters, sort and no geo rules ', () => {
const searchParams = adaptSearchParams({
indexUid: 'test',
paginationTotalHits: 20,
facetFilters: [['genres:Drama', 'genres:Thriller'], ['title:Ariel']],
sort: 'id < 1',
})
expect(searchParams.filter).toStrictEqual([
['genres="Drama"', 'genres="Thriller"'],
['title="Ariel"'],
])
expect(searchParams.sort).toStrictEqual(['id < 1'])
expect(searchParams.attributesToHighlight).toContain('*')
expect(searchParams.attributesToHighlight?.length).toBe(1)
})
test('Adapt SearchContext with filters, sort and geo rules ', () => {
const searchParams = adaptSearchParams({
indexUid: 'test',
paginationTotalHits: 20,
facetFilters: [['genres:Drama', 'genres:Thriller'], ['title:Ariel']],
insideBoundingBox: '0,0,0,0',
sort: 'id < 1',
})
expect(searchParams.filter).toStrictEqual([
'_geoRadius(0, 0, 0)',
['genres="Drama"', 'genres="Thriller"'],
['title="Ariel"'],
])
expect(searchParams.sort).toStrictEqual(['_geoPoint(0, 0):asc', 'id < 1'])
expect(searchParams.attributesToHighlight).toContain('*')
expect(searchParams.attributesToHighlight?.length).toBe(1)
})
test('Adapt SearchContext with only facetFilters and geo rules ', () => {
const searchParams = adaptSearchParams({
indexUid: 'test',
paginationTotalHits: 20,
facetFilters: [['genres:Drama', 'genres:Thriller'], ['title:Ariel']],
insideBoundingBox: '0,0,0,0',
})
expect(searchParams.filter).toEqual([
'_geoRadius(0, 0, 0)',
['genres="Drama"', 'genres="Thriller"'],
['title="Ariel"'],
])
expect(searchParams.attributesToHighlight).toContain('*')
expect(searchParams.attributesToHighlight?.length).toBe(1)
})
test('Adapt SearchContext with only sort and geo rules ', () => {
const searchParams = adaptSearchParams({
indexUid: 'test',
paginationTotalHits: 20,
insideBoundingBox: '0,0,0,0',
sort: 'id < 1',
})
expect(searchParams.filter).toEqual(['_geoRadius(0, 0, 0)'])
expect(searchParams.sort).toStrictEqual(['_geoPoint(0, 0):asc', 'id < 1'])
expect(searchParams.attributesToHighlight).toContain('*')
expect(searchParams.attributesToHighlight?.length).toBe(1)
})
test('Adapt SearchContext with no sort abd no filters and geo rules ', () => {
const searchParams = adaptSearchParams({
indexUid: 'test',
paginationTotalHits: 20,
insideBoundingBox: '0,0,0,0',
})
expect(searchParams.filter).toEqual(['_geoRadius(0, 0, 0)'])
expect(searchParams.sort).toStrictEqual(['_geoPoint(0, 0):asc'])
expect(searchParams.attributesToHighlight).toContain('*')
expect(searchParams.attributesToHighlight?.length).toBe(1)
})
Current Behavior
When moving inside the Google Maps, search results are returned based on its position. To determine what documents should be returned, instant-meilisearch calculates the middle point of the Maps window and the distance between each corner. It then creates a filter (see geo filter documentation based on that middle point and the distance between each corner.
No sorting
The first itteration of instant-meilisearch's geosearch also provided by default a sort rule whereas geo points closer to the center of the map were considered more important than other. Which created packs of markers in the center of the map:
By removing them, the markers are more scattered, which make the maps look nicer:
But what if we want to sort?
Without providing by default the sorting feature, we still want to provide the possibility to the user to sort its markers to be as close as possible to the center.
Solution
To enable sorting from the center point of the map, the solution is to provide a parameter
proximityGeoRule
in the instantMeiliSearch parameters. Which would default to false.This will enable sorting.
Here are the steps to follow to implement this feature:
1. add a
proximityGeoRule
in the InstantMeiliSearch Parameter2. Add the information in the geoSearchContext
3. Use the information in the geo-rule adapter
In
geo-rules-adapter.ts
ifproximityGeoRule
is set to true, sort filter should be added:4. make
aroundLatLng
work withoutaroundRadius
Because aroundLatLng only provided a middle point, and not a radius, only a sort was previously done.
Because of a lack of
radius
provided, we cannot create afilter
is not possible.Thus, if
proximityGeoRule
is set to true, the following condition should be added ingeo-rules-adapter.ts
5. Add the sort in the search params adapter.
In the search params adapter filter from the geosearch adapter are added in the final search requests parameters sent to MeiliSearch.
The same should be added for
sort
:6. add tests
This behavior should be tested in
geosearch.tests.ts