Add categories to places
Some checks failed
CI / main (push) Failing after 3m46s

This commit is contained in:
Broks Randolfs Gailītis 2025-03-15 18:11:28 +02:00
parent d721f2876e
commit 30db53bd95
11 changed files with 109 additions and 45 deletions

View File

@ -0,0 +1,38 @@
/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
exports.up = function(knex) {
return knex.schema
.createTable('categories', function (table) {
table.uuid('id').primary().defaultTo(knex.raw(`gen_random_uuid()`));
table.string('name').notNullable();
table.timestamps(true, true);
})
.alterTable('places', function(table) {
table.uuid('category_id').references('id').inTable('categories')
})
.createTable('subcategories', function(table) {
table.uuid('id').primary().defaultTo(knex.raw(`gen_random_uuid()`));
table.string('name').notNullable();
table.uuid('category_id').references('id').inTable('categories').onDelete('CASCADE');
table.timestamps(true, true);
})
.createTable('place_subcategories', function(table) {
table.uuid('place_id').references('id').inTable('places').onDelete('CASCADE');
table.uuid('subcategory_id').references('id').inTable('subcategories').onDelete('CASCADE');
})
};
/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
exports.down = function(knex) {
knex.schema.alterTable('places', function(table) {
table.dropColumn('category_id');
});
knex.schema.dropTable('categories');
knex.schema.dropTable('subcategories');
knex.schema.dropTable('place_subcategories');
};

View File

@ -74,7 +74,7 @@
"defaultConfiguration": "development",
"options": {
"cwd": "apps/blakus-api",
"command": "npx knex migrate:make farts"
"command": "npx knex migrate:make new"
},
"schema": {
"name": {

View File

@ -0,0 +1,10 @@
const CATEGORIES = require('./categories.json');
/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
exports.seed = async function(knex) {
await knex('categories').del()
await knex('categories').insert(CATEGORIES.map(({name}) => ({name})));
};

View File

@ -0,0 +1,10 @@
[
{ "name": "restaurant", "subcategories": [] },
{ "name": "cafe", "subcategories": [] },
{ "name": "bar", "subcategories": [] },
{ "name": "pub", "subcategories": [] },
{ "name": "biergarten", "subcategories": [] },
{ "name": "fast_food", "subcategories": [] },
{ "name": "food_court", "subcategories": [] },
{ "name": "ice_cream", "subcategories": [] }
]

View File

@ -1,5 +1,5 @@
const { fakerLV : faker } = require('@faker-js/faker');
// const CATEGORIES = require('./categories.json');
const PLACE_COUNT = 1000;
const BBOX_RIGA = [23.755875,56.815914,24.466553,57.067617];
const [ BBOX_MIN_LAT, BBOX_MIN_LON, BBOX_MAX_LAT, BBOX_MAX_LON ] = BBOX_RIGA;
@ -10,6 +10,8 @@ const [ BBOX_MIN_LAT, BBOX_MIN_LON, BBOX_MAX_LAT, BBOX_MAX_LON ] = BBOX_RIGA;
*/
exports.seed = async function(knex) {
const categories = await knex('categories').select('id');
const createPlace = () => {
const coords = [
faker.location.latitude({ min: BBOX_MIN_LAT, max: BBOX_MAX_LAT }),
@ -26,12 +28,13 @@ exports.seed = async function(knex) {
street: faker.location.street(),
house: faker.helpers.maybe(() => faker.person.lastName(), { probability: 0.1 }) || faker.location.buildingNumber(),
postalCode: faker.location.zipCode(),
category_id: faker.helpers.arrayElement(categories.map(c => c.id)),
}
};
const places = new Array(PLACE_COUNT).fill(() => createPlace()).map((fn, i) => fn(i));
// Deletes ALL existing entries
await knex('places').del()
await knex('places').insert([
...new Array(PLACE_COUNT).fill(() => createPlace()).map((fn, i) => fn(i)),
]);
await knex('places').insert(places);
};

View File

@ -18,7 +18,7 @@ export default async function (fastify: FastifyInstance) {
properties: {
id: { type: 'string' },
title: { type: 'string' },
amenity: { type: 'string' },
category: { type: 'string' },
address: {
type: 'object',
properties: {
@ -51,23 +51,26 @@ export default async function (fastify: FastifyInstance) {
}, async function (request, reply) {
const {lat, lon} = request.query;
const knownPlaces = await db.select(
'id',
'name',
'externalId',
'country',
'county',
'district',
'city',
'street',
'house',
'postalCode',
db.raw('ST_Y(coordinates::geometry) AS lat'),
db.raw('ST_X(coordinates::geometry) AS lon')
).whereRaw(
'ST_DWithin(coordinates, ST_SetSRID(ST_MakePoint(?, ?), 4326), ?)',
[lon, lat, 2000]
).from('places');
const knownPlaces = await db('places')
.leftJoin('categories', 'places.category_id', 'categories.id')
.select(
'places.id',
'places.name',
'places.externalId',
'places.country',
'places.county',
'places.district',
'places.city',
'places.street',
'places.house',
'places.postalCode',
db.raw('ST_Y(places.coordinates::geometry) AS lat'),
db.raw('ST_X(places.coordinates::geometry) AS lon'),
'categories.name AS category'
).whereRaw(
'ST_DWithin(places.coordinates, ST_SetSRID(ST_MakePoint(?, ?), 4326), ?)',
[lon, lat, 2000]
);
// const externalIds = await db.select('externalId').from('places').where('externalId', 'like', 'osm:%');
@ -97,7 +100,7 @@ export default async function (fastify: FastifyInstance) {
const blakus = knownPlaces.map(place => ({
id: place.id,
title: place.name,
amenity: 'pub',
category: place.category,
address: {
country: place.country,
county: place.county,

View File

@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="_amenity_restaurant_CYImm">"Restaurant"</string>
<string name="_amenity_pub_hVjSx">"Pub"</string>
<string name="_amenity_ice_cream_12K4Gu">"Ice Cream"</string>
<string name="_amenity_food_court_Z2qUk6P">"Food Court"</string>
<string name="_amenity_fast_food_Z1zDs8J">"Fast Food"</string>
<string name="_amenity_cafe_Z13hX6o">"Cafe"</string>
<string name="_amenity_biergarten_zXiC4">"Beer Garden"</string>
<string name="_amenity_bar_hVg75">"Bar"</string>
<string name="_category_restaurant_ZNNv4O">"Restaurant"</string>
<string name="_category_pub_uGSaR">"Pub"</string>
<string name="_category_ice_cream_Z1ic9A2">"Ice Cream"</string>
<string name="_category_food_court_1bszfU">"Food Court"</string>
<string name="_category_fast_food_19ArnF">"Fast Food"</string>
<string name="_category_cafe_laiRP">"Cafe"</string>
<string name="_category_biergarten_ZQOUO7">"Beer Garden"</string>
<string name="_category_bar_uGOop">"Bar"</string>
<string name="_app_name_1k3Sbz">"Blakus"</string>
<string name="app_name">"Blakus"</string>
<string name="title_activity_kimera">"Blakus"</string>

View File

@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="_amenity_restaurant_CYImm">"Restorāns"</string>
<string name="_amenity_pub_hVjSx">"Krogs"</string>
<string name="_amenity_ice_cream_12K4Gu">"Saldējums"</string>
<string name="_amenity_food_court_Z2qUk6P">"Ēdināšanas laukums"</string>
<string name="_amenity_fast_food_Z1zDs8J">"Ātras uzkodas"</string>
<string name="_amenity_cafe_Z13hX6o">"Kafejnīca"</string>
<string name="_amenity_biergarten_zXiC4">"Biergarten"</string>
<string name="_amenity_bar_hVg75">"Bārs"</string>
<string name="_category_restaurant_ZNNv4O">"Restorāns"</string>
<string name="_category_pub_uGSaR">"Krogs"</string>
<string name="_category_ice_cream_Z1ic9A2">"Saldējums"</string>
<string name="_category_food_court_1bszfU">"Ēdināšanas laukums"</string>
<string name="_category_fast_food_19ArnF">"Ātras uzkodas"</string>
<string name="_category_cafe_laiRP">"Kafejnīca"</string>
<string name="_category_biergarten_ZQOUO7">"Biergarten"</string>
<string name="_category_bar_uGOop">"Bārs"</string>
<string name="_app_name_1k3Sbz">"Blakus"</string>
<string name="app_name">"Blakus"</string>
<string name="title_activity_kimera">"Blakus"</string>

View File

@ -1,6 +1,6 @@
{
"app.name": "Blakus",
"amenity": {
"category": {
"bar": "Bar",
"biergarten": "Beer Garden",
"cafe": "Cafe",

View File

@ -1,6 +1,6 @@
{
"app.name": "Blakus",
"amenity": {
"category": {
"bar": "Bārs",
"biergarten": "Biergarten",
"cafe": "Kafejnīca",

View File

@ -25,7 +25,7 @@ type ReverseGeocodeResult = {
type BlakusItem = {
id: string;
title: string;
amenity: string;
category: string;
tags: Record<string, string>;
affinity: number;
coords: {
@ -88,7 +88,7 @@ export class HelloWorldModel extends Observable {
this.items = await this.getBlakus(params);
this.items.forEach(({ coords, title, amenity, affinity, id }) => {
this.items.forEach(({ coords, title, category, affinity, id }) => {
this.#map.addMarker({
id,
position: {
@ -97,7 +97,7 @@ export class HelloWorldModel extends Observable {
},
detail: {
title,
description: localize(`amenity.${amenity}`),
description: localize(`category.${category}`),
affinity
}
})