Skip to content

Commit

Permalink
Merge pull request #56 from wearefuturegov/TOP-244-when-searching-for…
Browse files Browse the repository at this point in the history
…-keyword-and-location-results-arent-ordered-by-distance

TOP-244 When searching for keyword and location results aren't ordere…
  • Loading branch information
apricot13 authored Jul 27, 2024
2 parents 7ad3383 + 1a48da8 commit 2dc6556
Show file tree
Hide file tree
Showing 10 changed files with 572 additions and 128 deletions.
40 changes: 0 additions & 40 deletions __tests__/unit/lib/filters.test.js
Original file line number Diff line number Diff line change
@@ -1,45 +1,5 @@
const filters = require("./../../../src/lib/filters")

describe("filterLocation", () => {
it("should return an empty object if lat and lng are not provided", () => {
expect(filters.filterLocation()).toEqual({})
})

it("should return a query object if lat and lng are provided", () => {
const lat = "40.7128"
const lng = "-74.0060"
const expectedQuery = {
"service_at_locations.location.geometry": {
$geoWithin: {
$centerSphere: [[parseFloat(lng), parseFloat(lat)], 20 / 3963.2],
},
},
}
expect(filters.filterLocation(lat, lng, false)).toEqual(expectedQuery)
})

it("should return a different query object if lat and lng and keywordSearch are provided", () => {
const lat = "40.7128"
const lng = "-74.0060"
const expectedQuery = {
$or: [
{
"service_at_locations.location.geometry": {
$geoWithin: {
$centerSphere: [
[parseFloat(lng), parseFloat(lat)],
20 / 3963.2, // miles x 1609.34 = Distance in meters
],
},
},
},
{ "service_at_locations.location.geometry": { $exists: false } },
],
}
expect(filters.filterLocation(lat, lng, true)).toEqual(expectedQuery)
})
})

describe("Calling visibleNow", () => {
it("should return a query that checks if a document is visible now", () => {
const query = filters.visibleNow()
Expand Down
112 changes: 112 additions & 0 deletions __tests__/unit/lib/locations.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
const getServices = require("../../../src/controllers/v1/services/routes/get-services")
const locations = require("./../../../src/lib/locations")

describe("filterLocationNearest", () => {
test("should return null when the list of locations is empty", async () => {
const lat = undefined
const lng = undefined
const { proximity } = await getServices.parseRequestParameters({})
expect(locations.filterLocationNearest(lat, lng, proximity)).toEqual({})
})

test("should return results when lat and lng is set", async () => {
const lat = parseFloat(1)
const lng = parseFloat(1.2)
const { proximity } = await getServices.parseRequestParameters({ lat, lng })
expect(locations.filterLocationNearest(lat, lng, proximity)).toEqual({
"service_at_locations.location.geometry": {
$nearSphere: {
$geometry: {
coordinates: [lng, lat],
type: "Point",
},
$maxDistance: proximity,
},
},
})
})

test("should return results when one or another lat/lng is 0", async () => {
const lat = parseFloat(0)
const lng = parseFloat(1.2)
const { proximity } = await getServices.parseRequestParameters({ lat, lng })
expect(locations.filterLocationNearest(lat, lng, proximity)).toEqual({
"service_at_locations.location.geometry": {
$nearSphere: {
$geometry: {
coordinates: [lng, lat],
type: "Point",
},
$maxDistance: proximity,
},
},
})
})
})

describe("filterLocationKeywords", () => {
test("should return an empty object when no keywords", async () => {
const keywords = undefined
const parameters = await getServices.parseRequestParameters({})
const result = await locations.filterLocationKeywords(keywords, parameters)
expect(result).toEqual({})
})

// test("should return a list of ids", async () => {
// const keywords = "SEND peer support"
// const parameters = await getServices.parseRequestParameters({})
// const result = await locations.filterLocationKeywords(keywords, parameters)
// expect(locations.filterLocationKeywords(keywords, parameters)).toEqual({
// $and: [
// { keyword: "test" },
// { filter: "test" },
// {
// "service_at_locations.location.geometry": {
// $exists: true,
// $ne: null,
// },
// },
// ],
// })
// })
})

describe("filterLocation", () => {
it("should return an empty object if lat and lng are not provided", () => {
expect(locations.filterLocation()).toEqual({})
})

it("should return a query object if lat and lng are provided", () => {
const lat = "40.7128"
const lng = "-74.0060"
const expectedQuery = {
"service_at_locations.location.geometry": {
$geoWithin: {
$centerSphere: [[parseFloat(lng), parseFloat(lat)], 20 / 3963.2],
},
},
}
expect(locations.filterLocation(lat, lng, false)).toEqual(expectedQuery)
})

it("should return a different query object if lat and lng and keywordSearch are provided", () => {
const lat = "40.7128"
const lng = "-74.0060"
const expectedQuery = {
$or: [
{
"service_at_locations.location.geometry": {
$geoWithin: {
$centerSphere: [
[parseFloat(lng), parseFloat(lat)],
20 / 3963.2, // miles x 1609.34 = Distance in meters
],
},
},
},
{ "service_at_locations.location.geometry": { $exists: false } },
],
}
expect(locations.filterLocation(lat, lng, true)).toEqual(expectedQuery)
})
})
35 changes: 35 additions & 0 deletions __tests__/unit/lib/queries.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const queries = require("./../../../src/lib/queries")

describe("queryType", () => {
test('should return "keyword" when only keywords are provided', () => {
const parameters = { keywords: "test" }
expect(queries.queryType(parameters)).toBe("keyword")
})

test('should return "location" when only lat and lng are provided', () => {
const parameters = { lat: 51.5074, lng: -0.1278 }
expect(queries.queryType(parameters)).toBe("location")
})

test('should return "keyword_location" when keywords, lat, and lng are all provided', () => {
const parameters = { keywords: "test", lat: 51.5074, lng: -0.1278 }
expect(queries.queryType(parameters)).toBe("keyword_location")
})

test("should return undefined when none of the parameters are provided", () => {
const parameters = {}
expect(queries.queryType(parameters)).toBeUndefined()
})

test("should return undefined when keywords is provided but lat and lng are missing", () => {
const parameters = { keywords: "test", lat: undefined, lng: undefined }
expect(queries.queryType(parameters)).toBe("keyword")
})

test("should return undefined when lat and lng are provided but keywords is missing", () => {
const parameters = { keywords: undefined, lat: 51.5074, lng: -0.1278 }
expect(queries.queryType(parameters)).toBe("location")
})
})

describe("addFilters", () => {})
6 changes: 4 additions & 2 deletions __tests__/unit/v1/services/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ describe("index", () => {
const next = jest.fn()

const parameters = { perPage: 10, page: 2 }
const queryType = undefined
const query = { id: 123 }
const results = [{ id: 123, name: "Test Service" }]
const count = 1
Expand All @@ -31,11 +32,12 @@ describe("index", () => {

expect(getServices.parseRequestParameters).toHaveBeenCalledWith(req.query)

expect(getServices.buildQuery).toHaveBeenCalledWith(parameters)
expect(getServices.buildQuery).toHaveBeenCalledWith(parameters, queryType)
expect(getServices.executeQuery).toHaveBeenCalledWith(
query,
parameters.perPage,
parameters.page
parameters.page,
queryType
)
expect(getServices.buildContent).toHaveBeenCalledWith(
results,
Expand Down
1 change: 1 addition & 0 deletions __tests__/unit/v1/services/routes/get-services.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ describe("get-services", () => {
it("should return thes parameters when no query parameters are provided", async () => {
const expectedResults = {
perPage: 50,
proximity: 8046.7,
page: 1,
keywords: undefined,
location: undefined,
Expand Down
9 changes: 7 additions & 2 deletions src/controllers/v1/services/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const logger = require("../../../../utils/logger")
const queries = require("../../../lib/queries")
const { getServices, getService } = require("./routes")

module.exports = {
Expand Down Expand Up @@ -33,12 +34,16 @@ module.exports = {
const parameters = await getServices.parseRequestParameters(req.query)
logger.info(parameters)

const query = await getServices.buildQuery(parameters)
const queryType = queries.queryType(parameters)
logger.info(`ℹ️ Query type is "${queryType}"`)

const query = await getServices.buildQuery(parameters, queryType)

const { results, count } = await getServices.executeQuery(
query,
parameters.perPage,
parameters.page
parameters.page,
queryType
)
const content = getServices.buildContent(
results,
Expand Down
Loading

0 comments on commit 2dc6556

Please sign in to comment.