mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-13 07:46:06 +00:00
feat(backend): distanceToMe (#8462)
* calculate distance between current user and queried user * fix query for unset location * use database to calculate distance * rename distance to distance to me, 100% calculation done in DB * distanceToMe tests * lint fixes
This commit is contained in:
parent
c855554825
commit
21f343b8cf
@ -50,6 +50,7 @@ type User {
|
||||
|
||||
locationName: String
|
||||
location: Location @cypher(statement: "MATCH (this)-[:IS_IN]->(l:Location) RETURN l")
|
||||
distanceToMe: Int
|
||||
about: String
|
||||
socialMedia: [SocialMedia]! @relation(name: "OWNED_BY", direction: "IN")
|
||||
|
||||
|
||||
@ -660,6 +660,202 @@ const emailNotificationSettingsMutation = gql`
|
||||
}
|
||||
`
|
||||
|
||||
const distanceToMeQuery = gql`
|
||||
query ($id: ID!) {
|
||||
User(id: $id) {
|
||||
distanceToMe
|
||||
}
|
||||
}
|
||||
`
|
||||
let myPlaceUser, otherPlaceUser, noCordsPlaceUser, noPlaceUser
|
||||
|
||||
describe('distanceToMe', () => {
|
||||
beforeEach(async () => {
|
||||
const Hamburg = await Factory.build('location', {
|
||||
id: 'region.5127278006398860',
|
||||
name: 'Hamburg',
|
||||
type: 'region',
|
||||
lng: 10.0,
|
||||
lat: 53.55,
|
||||
nameES: 'Hamburgo',
|
||||
nameFR: 'Hambourg',
|
||||
nameIT: 'Amburgo',
|
||||
nameEN: 'Hamburg',
|
||||
namePT: 'Hamburgo',
|
||||
nameDE: 'Hamburg',
|
||||
nameNL: 'Hamburg',
|
||||
namePL: 'Hamburg',
|
||||
nameRU: 'Гамбург',
|
||||
})
|
||||
const Germany = await Factory.build('location', {
|
||||
id: 'country.10743216036480410',
|
||||
name: 'Germany',
|
||||
type: 'country',
|
||||
namePT: 'Alemanha',
|
||||
nameDE: 'Deutschland',
|
||||
nameES: 'Alemania',
|
||||
nameNL: 'Duitsland',
|
||||
namePL: 'Niemcy',
|
||||
nameFR: 'Allemagne',
|
||||
nameIT: 'Germania',
|
||||
nameEN: 'Germany',
|
||||
nameRU: 'Германия',
|
||||
})
|
||||
const Paris = await Factory.build('location', {
|
||||
id: 'region.9397217726497330',
|
||||
name: 'Paris',
|
||||
type: 'region',
|
||||
lng: 2.35183,
|
||||
lat: 48.85658,
|
||||
nameES: 'París',
|
||||
nameFR: 'Paris',
|
||||
nameIT: 'Parigi',
|
||||
nameEN: 'Paris',
|
||||
namePT: 'Paris',
|
||||
nameDE: 'Paris',
|
||||
nameNL: 'Parijs',
|
||||
namePL: 'Paryż',
|
||||
nameRU: 'Париж',
|
||||
})
|
||||
|
||||
user = await Factory.build('user', {
|
||||
id: 'user',
|
||||
role: 'user',
|
||||
})
|
||||
await user.relateTo(Hamburg, 'isIn')
|
||||
|
||||
myPlaceUser = await Factory.build('user', {
|
||||
id: 'myPlaceUser',
|
||||
role: 'user',
|
||||
})
|
||||
await myPlaceUser.relateTo(Hamburg, 'isIn')
|
||||
|
||||
otherPlaceUser = await Factory.build('user', {
|
||||
id: 'otherPlaceUser',
|
||||
role: 'user',
|
||||
})
|
||||
await otherPlaceUser.relateTo(Paris, 'isIn')
|
||||
|
||||
noCordsPlaceUser = await Factory.build('user', {
|
||||
id: 'noCordsPlaceUser',
|
||||
role: 'user',
|
||||
})
|
||||
await noCordsPlaceUser.relateTo(Germany, 'isIn')
|
||||
|
||||
noPlaceUser = await Factory.build('user', {
|
||||
id: 'noPlaceUser',
|
||||
role: 'user',
|
||||
})
|
||||
})
|
||||
|
||||
describe('query the field', () => {
|
||||
describe('for self user', () => {
|
||||
it('returns null', async () => {
|
||||
authenticatedUser = await user.toJson()
|
||||
const targetUser = await user.toJson()
|
||||
await expect(
|
||||
query({ query: distanceToMeQuery, variables: { id: targetUser.id } }),
|
||||
).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
data: {
|
||||
User: [
|
||||
{
|
||||
distanceToMe: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
errors: undefined,
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('for myPlaceUser', () => {
|
||||
it('returns 0', async () => {
|
||||
authenticatedUser = await user.toJson()
|
||||
const targetUser = await myPlaceUser.toJson()
|
||||
await expect(
|
||||
query({ query: distanceToMeQuery, variables: { id: targetUser.id } }),
|
||||
).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
data: {
|
||||
User: [
|
||||
{
|
||||
distanceToMe: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
errors: undefined,
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('for otherPlaceUser', () => {
|
||||
it('returns a number', async () => {
|
||||
authenticatedUser = await user.toJson()
|
||||
const targetUser = await otherPlaceUser.toJson()
|
||||
await expect(
|
||||
query({ query: distanceToMeQuery, variables: { id: targetUser.id } }),
|
||||
).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
data: {
|
||||
User: [
|
||||
{
|
||||
distanceToMe: 746,
|
||||
},
|
||||
],
|
||||
},
|
||||
errors: undefined,
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('for noCordsPlaceUser', () => {
|
||||
it('returns null', async () => {
|
||||
authenticatedUser = await user.toJson()
|
||||
const targetUser = await noCordsPlaceUser.toJson()
|
||||
await expect(
|
||||
query({ query: distanceToMeQuery, variables: { id: targetUser.id } }),
|
||||
).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
data: {
|
||||
User: [
|
||||
{
|
||||
distanceToMe: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
errors: undefined,
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('for noPlaceUser', () => {
|
||||
it('returns null', async () => {
|
||||
authenticatedUser = await user.toJson()
|
||||
const targetUser = await noPlaceUser.toJson()
|
||||
await expect(
|
||||
query({ query: distanceToMeQuery, variables: { id: targetUser.id } }),
|
||||
).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
data: {
|
||||
User: [
|
||||
{
|
||||
distanceToMe: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
errors: undefined,
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('emailNotificationSettings', () => {
|
||||
beforeEach(async () => {
|
||||
user = await Factory.build('user', {
|
||||
|
||||
@ -467,6 +467,36 @@ export default {
|
||||
},
|
||||
},
|
||||
User: {
|
||||
distanceToMe: async (parent, _params, context, _resolveInfo) => {
|
||||
// is it myself?
|
||||
if (parent.id === context.user.id) {
|
||||
return null
|
||||
}
|
||||
|
||||
const session = context.driver.session()
|
||||
|
||||
const query = session.readTransaction(async (transaction) => {
|
||||
const result = await transaction.run(
|
||||
`
|
||||
MATCH (user:User {id: $parent.id})-[:IS_IN]->(userLoc:Location)
|
||||
MATCH (me:User {id: $user.id})-[:IS_IN]->(meLoc:Location)
|
||||
WITH
|
||||
point({latitude: userLoc.lat, longitude: userLoc.lng}) as userPoint,
|
||||
point({latitude: meLoc.lat, longitude: meLoc.lng}) as mePoint
|
||||
RETURN round(point.distance(userPoint, mePoint) / 1000) as distance
|
||||
`,
|
||||
{ parent, user: context.user },
|
||||
)
|
||||
|
||||
return result.records.map((record) => record.get('distance'))[0]
|
||||
})
|
||||
|
||||
try {
|
||||
return await query
|
||||
} finally {
|
||||
session.close()
|
||||
}
|
||||
},
|
||||
emailNotificationSettings: async (parent, _params, _context, _resolveInfo) => {
|
||||
return [
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user