From 6b6569aa05a7d6124043a2b43bbe2e8d6de610e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Broks=20Randolfs=20Gail=C4=ABtis?= Date: Sat, 15 Mar 2025 19:42:20 +0200 Subject: [PATCH] Use place ratings (temp affinity) --- .../20250315172409_place_ratings.js | 22 +++++++++++++++++ apps/blakus-api/seeds/users.js | 24 +++++++++++++++++-- apps/blakus-api/src/app/routes/blakus.ts | 11 ++++++--- 3 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 apps/blakus-api/migrations/20250315172409_place_ratings.js diff --git a/apps/blakus-api/migrations/20250315172409_place_ratings.js b/apps/blakus-api/migrations/20250315172409_place_ratings.js new file mode 100644 index 0000000..4a3d930 --- /dev/null +++ b/apps/blakus-api/migrations/20250315172409_place_ratings.js @@ -0,0 +1,22 @@ +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.up = function(knex) { + return knex.schema + .createTable('place_ratings', function (table) { + table.uuid('id').primary().defaultTo(knex.raw(`gen_random_uuid()`)); + table.uuid('place_id').references('id').inTable('places').onDelete('CASCADE'); + table.uuid('user_id').references('id').inTable('users').onDelete('CASCADE'); + table.integer('rating').notNullable(); + table.timestamps(true, true); + }) +}; + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.down = function(knex) { + knex.schema.dropTable('place_ratings'); +}; diff --git a/apps/blakus-api/seeds/users.js b/apps/blakus-api/seeds/users.js index 056363f..c18c207 100644 --- a/apps/blakus-api/seeds/users.js +++ b/apps/blakus-api/seeds/users.js @@ -1,4 +1,5 @@ const { fakerLV : faker } = require('@faker-js/faker'); +const { randomUUID } = require('crypto'); const USER_COUNT = 500; @@ -8,6 +9,8 @@ const USER_COUNT = 500; */ exports.seed = async function(knex) { + const places = await knex('places').select('id'); + const createUser = ({ sex = faker.person.sexType(), first_name = `${faker.person.firstName(sex)}`, @@ -15,13 +18,14 @@ exports.seed = async function(knex) { email = faker.internet.email({ lastName: last_name, firstName: first_name }).toLocaleLowerCase(), } = {}) => { return { + id: randomUUID(), first_name, last_name, email, } }; - await knex('users').insert([ + const users = [ createUser({ first_name: 'Broks Randolfs', last_name: 'Gailītis', @@ -32,5 +36,21 @@ exports.seed = async function(knex) { last_name: 'Gailīte' }), ...new Array(USER_COUNT).fill(() => createUser()).map((fn, i) => fn(i)), - ]); + ]; + + await knex('users').insert(users); + + // Generate multiple random place ratings for each user + for (const user of users) { + const placeIds = faker.helpers.arrayElements(places, { min: 1, max: 10 }); + for (const placeId of placeIds) { + await knex('place_ratings').insert({ + id: randomUUID(), + user_id: user.id, + place_id: placeId.id, + rating: faker.number.int({ min: 1, max: 5 }), + }); + } + } + }; diff --git a/apps/blakus-api/src/app/routes/blakus.ts b/apps/blakus-api/src/app/routes/blakus.ts index 8f58a0f..acd8ef0 100644 --- a/apps/blakus-api/src/app/routes/blakus.ts +++ b/apps/blakus-api/src/app/routes/blakus.ts @@ -53,6 +53,8 @@ export default async function (fastify: FastifyInstance) { const knownPlaces = await db('places') .leftJoin('categories', 'places.category_id', 'categories.id') + .join('place_ratings', 'places.id', 'place_ratings.place_id') + .avg('place_ratings.rating AS affinity') // TODO: work on real affinity score .select( 'places.id', 'places.name', @@ -67,10 +69,13 @@ export default async function (fastify: FastifyInstance) { db.raw('ST_Y(places.coordinates::geometry) AS lat'), db.raw('ST_X(places.coordinates::geometry) AS lon'), 'categories.name AS category' - ).whereRaw( + ) + .whereRaw( 'ST_DWithin(places.coordinates, ST_SetSRID(ST_MakePoint(?, ?), 4326), ?)', [lon, lat, 2000] - ); + ) + .groupBy('places.id', 'categories.name') + .orderBy('affinity', 'desc') // const externalIds = await db.select('externalId').from('places').where('externalId', 'like', 'osm:%'); @@ -114,7 +119,7 @@ export default async function (fastify: FastifyInstance) { lat: place.lat, lon: place.lon, }, - affinity: Math.floor(Math.random() * 101) // TODO: this is just a placeholder for "affinity" calculation + affinity: place.affinity // TODO: this is just a placeholder for "affinity" calculation })); reply.send(blakus);