Komplettumstieg auf drizzle

This commit is contained in:
2024-04-20 20:48:18 +02:00
parent c4cdcf4505
commit c90d6b72b7
31 changed files with 18911 additions and 186 deletions

View File

@@ -1,7 +1,5 @@
import { Inject, Injectable } from '@nestjs/common';
import {
BusinessListing,
CommercialPropertyListing,
ListingCriteria,
ListingType,
ImageProperty,
@@ -12,8 +10,8 @@ import { convertStringToNullUndefined } from '../utils.js';
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
import { Logger } from 'winston';
import { EntityData, EntityId, Schema, SchemaDefinition } from 'redis-om';
import { SQL, eq, ilike, sql } from 'drizzle-orm';
import { BusinessesJson, PG_CONNECTION, businesses_json, commercials_json } from '../drizzle/schema.js';
import { SQL, eq, gte, ilike, lte, sql, and} from 'drizzle-orm';
import { BusinessListing, CommercialPropertyListing, PG_CONNECTION, businesses, commercials, } from '../drizzle/schema.js';
import { NodePgDatabase } from 'drizzle-orm/node-postgres';
import * as schema from '../drizzle/schema.js';
import { PgTableFn, PgTableWithColumns, QueryBuilder } from 'drizzle-orm/pg-core';
@@ -24,69 +22,86 @@ export class ListingsService {
constructor(@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger,
@Inject(PG_CONNECTION) private conn: NodePgDatabase<typeof schema>,) {
}
private buildWhereClause(criteria: ListingCriteria):SQL {
const finalSql = sql`1=1`;
finalSql.append(criteria.type?sql` AND data->>'type' = ${criteria.type}` : sql``)
finalSql.append(criteria.state ? sql` AND data->>'state' = ${criteria.state}` : sql``)
finalSql.append(criteria.minPrice ? sql` AND CAST(data->>'price' AS NUMERIC) >= ${parseFloat(criteria.minPrice)}` : sql``)
finalSql.append(criteria.maxPrice ? sql` AND CAST(data->>'price' AS NUMERIC) < ${parseFloat(criteria.maxPrice)}` : sql``)
finalSql.append(criteria.realEstateChecked !== undefined ? sql` AND CAST(data->>'realEstateIncluded' AS BOOLEAN) = ${criteria.realEstateChecked}` : sql``)
finalSql.append(criteria.title ? sql` AND LOWER(data->>'title') LIKE LOWER('%' || ${criteria.title} || '%')` : sql``)
return finalSql
// private buildWhereClause(criteria: ListingCriteria): SQL {
// const finalSql = sql`1=1`;
// finalSql.append(criteria.type ? sql` AND 'type' = ${criteria.type}` : sql``)
// finalSql.append(criteria.state ? sql` AND data->>'state' = ${criteria.state}` : sql``)
// finalSql.append(criteria.minPrice ? sql` AND CAST(data->>'price' AS NUMERIC) >= ${parseFloat(criteria.minPrice)}` : sql``)
// finalSql.append(criteria.maxPrice ? sql` AND CAST(data->>'price' AS NUMERIC) < ${parseFloat(criteria.maxPrice)}` : sql``)
// finalSql.append(criteria.realEstateChecked !== undefined ? sql` AND CAST(data->>'realEstateIncluded' AS BOOLEAN) = ${criteria.realEstateChecked}` : sql``)
// finalSql.append(criteria.title ? sql` AND LOWER(data->>'title') LIKE LOWER('%' || ${criteria.title} || '%')` : sql``)
// return finalSql
// }
private getConditions(criteria: ListingCriteria): any[] {
const conditions = [];
if (criteria.type) {
conditions.push(eq(businesses.type, criteria.type));
}
if (criteria.state) {
conditions.push(eq(businesses.state, criteria.state));
}
if (criteria.minPrice) {
conditions.push(gte(businesses.price, criteria.minPrice));
}
if (criteria.maxPrice) {
conditions.push(lte(businesses.price, criteria.maxPrice));
}
if (criteria.realEstateChecked) {
conditions.push(eq(businesses.realEstateIncluded, true));
}
if (criteria.title) {
conditions.push(ilike(businesses.title, `%${criteria.title}%`));
}
return conditions;
}
// ##############################################################
// Listings general
// ##############################################################
private async findListings(table: typeof businesses_json | typeof commercials_json, criteria: ListingCriteria ,start = 0, length = 12): Promise<any> {
const whereClause = this.buildWhereClause(criteria)
const [data, total] = await Promise.all([
(await this.conn.select({ id:table.id, data: table.data }).from(table).where(whereClause).offset(start).limit(length)).map(e=>{
const ret = e.data as any
ret.id = e.id
return ret
}),
this.conn.select({ count: sql`count(*)` }).from(table).where(whereClause).then((result) => Number(result[0].count)),
]);
return { total, data };
}
async findById(id: string, table: typeof businesses_json | typeof commercials_json): Promise<BusinessListing|CommercialPropertyListing> {
const result = await this.conn.select({ data: table.data }).from(table).where(sql`${table.id} = ${id}`)
return result[0].data as BusinessListing
}
async findListingsByCriteria(criteria: ListingCriteria, table: typeof businesses_json | typeof commercials_json): Promise<{ data: Record<string, any>[]; total: number }> {
async findListingsByCriteria(criteria: ListingCriteria, table: typeof businesses | typeof commercials): Promise<{ data: Record<string, any>[]; total: number }> {
const start = criteria.start ? criteria.start : 0;
const length = criteria.length ? criteria.length : 12;
return await this.findListings(table, criteria, start, length)
}
async findByPriceRange(minPrice: number, maxPrice: number, table: typeof businesses_json | typeof commercials_json): Promise<BusinessesJson[]> {
return this.conn.select().from(table).where(sql`${table.data}->>'price' BETWEEN ${minPrice} AND ${maxPrice}`);
private async findListings(table: typeof businesses | typeof commercials, criteria: ListingCriteria, start = 0, length = 12): Promise<any> {
const conditions = this.getConditions(criteria)
const [data, total] = await Promise.all([
this.conn.select().from(table).where(and(...conditions)).offset(start).limit(length),
this.conn.select({ count: sql`count(*)` }).from(table).where(and(...conditions)).then((result) => Number(result[0].count)),
]);
return { total, data };
}
async findById(id: string, table: typeof businesses | typeof commercials): Promise<BusinessListing | CommercialPropertyListing> {
const result = await this.conn.select().from(table).where(sql`${table.id} = ${id}`)
return result[0] as BusinessListing | CommercialPropertyListing
}
async findByState(state: string, table: typeof businesses_json | typeof commercials_json): Promise<BusinessesJson[]> {
return this.conn.select().from(table).where(sql`${table.data}->>'state' = ${state}`);
}
// async findByPriceRange(minPrice: number, maxPrice: number, table: typeof businesses | typeof commercials): Promise<BusinessesJson[]> {
// return this.conn.select().from(table).where(sql`${table}->>'price' BETWEEN ${minPrice} AND ${maxPrice}`);
// }
async findByUserId(userId: string, table: typeof businesses_json | typeof commercials_json): Promise<BusinessesJson[]> {
return this.conn.select().from(table).where(sql`${table.data}->>'userId' = ${userId}`);
// async findByState(state: string, table: typeof businesses | typeof commercials): Promise<BusinessesJson[]> {
// return this.conn.select().from(table).where(sql`${table}->>'state' = ${state}`);
// }
async findByUserId(userId: string, table: typeof businesses | typeof commercials): Promise<BusinessListing[] | CommercialPropertyListing[]> {
return await this.conn.select().from(table).where(eq(table.userId, userId)) as BusinessListing[] | CommercialPropertyListing[]
}
async findByTitleContains(title: string, table: typeof businesses_json | typeof commercials_json): Promise<BusinessesJson[]> {
return this.conn.select().from(table).where(sql`${table.data}->>'title' ILIKE '%' || ${title} || '%'`);
}
async createListing(data: BusinessListing, table: typeof businesses_json | typeof commercials_json): Promise<BusinessesJson> {
// async findByTitleContains(title: string, table: typeof businesses | typeof commercials): Promise<BusinessesJson[]> {
// return this.conn.select().from(table).where(sql`${table}->>'title' ILIKE '%' || ${title} || '%'`);
// }
async createListing(data: BusinessListing | CommercialPropertyListing, table: typeof businesses | typeof commercials): Promise<BusinessListing | CommercialPropertyListing> {
const newListing = { data, created: data.created, updated: data.updated, visits: 0, last_visit: null }
const [createdListing] = await this.conn.insert(table).values(newListing).returning();
return createdListing as BusinessesJson;
return createdListing as BusinessListing | CommercialPropertyListing;
}
async updateListing(id: string, data: BusinessListing | CommercialPropertyListing, table: typeof businesses_json | typeof commercials_json): Promise<BusinessesJson> {
async updateListing(id: string, data: BusinessListing | CommercialPropertyListing, table: typeof businesses | typeof commercials): Promise<BusinessListing | CommercialPropertyListing> {
const [updateListing] = await this.conn.update(table).set(data).where(eq(table.id, id)).returning();
return updateListing as BusinessesJson;
return updateListing as BusinessListing | CommercialPropertyListing;
}
async deleteListing(id: string, table: typeof businesses_json | typeof commercials_json): Promise<void> {
async deleteListing(id: string, table: typeof businesses | typeof commercials): Promise<void> {
await this.conn.delete(table).where(eq(table.id, id));
}
@@ -94,23 +109,23 @@ export class ListingsService {
// Images for commercial Properties
// ##############################################################
async updateImageOrder(id: string, imageOrder: ImageProperty[]) {
const listing = await this.findById(id, commercials_json) as unknown as CommercialPropertyListing
async updateImageOrder(id: string, imageOrder: string[]) {
const listing = await this.findById(id, commercials) as unknown as CommercialPropertyListing
listing.imageOrder = imageOrder;
await this.updateListing(listing.id, listing, commercials_json)
await this.updateListing(listing.id, listing, commercials)
}
async deleteImage(id: string, name: string,) {
const listing = await this.findById(id, commercials_json) as unknown as CommercialPropertyListing
const index = listing.imageOrder.findIndex(im => im.name === name);
const listing = await this.findById(id, commercials) as unknown as CommercialPropertyListing
const index = listing.imageOrder.findIndex(im => im === name);
if (index > -1) {
listing.imageOrder.splice(index, 1);
await this.updateListing(listing.id, listing, commercials_json)
await this.updateListing(listing.id, listing, commercials)
}
}
async addImage(id: string, imagename: string) {
const listing = await this.findById(id, commercials_json) as unknown as CommercialPropertyListing
listing.imageOrder.push({ name: imagename, code: '', id: '' });
await this.updateListing(listing.id, listing, commercials_json)
const listing = await this.findById(id, commercials) as unknown as CommercialPropertyListing
listing.imageOrder.push(imagename);
await this.updateListing(listing.id, listing, commercials)
}
// async getCommercialPropertyListingById(id: string): Promise<CommercialPropertyListing>{
// return await this.commercialPropertyListingRepository.fetch(id) as unknown as CommercialPropertyListing;