feat: insert province district sub-district into db
This commit is contained in:
parent
09cb20c57d
commit
23717bacaf
3 changed files with 7584 additions and 0 deletions
7437
assets/thailand-area.csv
Normal file
7437
assets/thailand-area.csv
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -8,6 +8,7 @@ import morgan from "./middlewares/morgan";
|
|||
import { RegisterRoutes } from "./routes";
|
||||
import { addUserRoles, createUser, getRoleByName, listUser } from "./services/keycloak";
|
||||
import prisma from "./db";
|
||||
import { initThailandAreaDatabase } from "./utils/thailand-area";
|
||||
|
||||
const APP_HOST = process.env.APP_HOST || "0.0.0.0";
|
||||
const APP_PORT = +(process.env.APP_PORT || 3000);
|
||||
|
|
@ -15,6 +16,8 @@ const APP_PORT = +(process.env.APP_PORT || 3000);
|
|||
(async () => {
|
||||
const app = express();
|
||||
|
||||
await initThailandAreaDatabase();
|
||||
|
||||
let users = await (async () => {
|
||||
let list = await listUser();
|
||||
while (!list) {
|
||||
|
|
|
|||
144
src/utils/thailand-area.ts
Normal file
144
src/utils/thailand-area.ts
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
import { parseFile } from "@fast-csv/parse";
|
||||
|
||||
import prisma from "../db";
|
||||
|
||||
export async function initThailandAreaDatabase() {
|
||||
const data = await new Promise<Record<string, string>[]>((resolve, reject) => {
|
||||
const r: Record<string, string>[] = [];
|
||||
const stream = parseFile("./assets/thailand-area.csv", { headers: true });
|
||||
stream.on("data", (v) => r.push(v));
|
||||
stream.on("error", (e) => reject(e));
|
||||
stream.on("end", () => resolve(r));
|
||||
}).catch((e) => console.error(e));
|
||||
|
||||
if (!data) return;
|
||||
|
||||
type Base = { id: string; name: string; nameEN: string };
|
||||
|
||||
const province: Base[] = [];
|
||||
const district: (Base & { provinceId: string })[] = [];
|
||||
const subDistrict: (Base & { zipCode: string; districtId: string })[] = [];
|
||||
|
||||
data.forEach((record) => {
|
||||
const provinceId = record["TambonID"].slice(0, 2);
|
||||
const districtId = record["TambonID"].slice(0, 4);
|
||||
const subDistrictId = record["TambonID"];
|
||||
|
||||
if (!province.find((v) => v.id === provinceId)) {
|
||||
province.push({
|
||||
id: provinceId,
|
||||
name: record["ProvinceThai"],
|
||||
nameEN: record["ProvinceEng"],
|
||||
});
|
||||
}
|
||||
if (!district.find((v) => v.id === districtId)) {
|
||||
district.push({
|
||||
id: districtId,
|
||||
name: record["DistrictThaiShort"],
|
||||
nameEN: record["DistrictEngShort"],
|
||||
provinceId,
|
||||
});
|
||||
}
|
||||
if (!subDistrict.find((v) => v.id === subDistrictId)) {
|
||||
subDistrict.push({
|
||||
id: subDistrictId,
|
||||
name: record["DistrictThaiShort"],
|
||||
nameEN: record["DistrictEngShort"],
|
||||
zipCode: record["PostCodeMain"],
|
||||
districtId,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function splitChunk<DataType, ResponseType>(
|
||||
array: DataType[],
|
||||
chunkSize: number,
|
||||
callback: (data: DataType[]) => ResponseType,
|
||||
) {
|
||||
const result: ReturnType<typeof callback>[] = [];
|
||||
for (let i = 0; i < array.length; i += chunkSize) {
|
||||
result.push(callback(array.slice(i, i + chunkSize)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
await prisma.$transaction(async (tx) => {
|
||||
const meta = {
|
||||
createdBy: null,
|
||||
createdAt: new Date(),
|
||||
updatedBy: null,
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
await Promise.all(
|
||||
splitChunk(province, 1000, async (r) => {
|
||||
return await tx.$kysely
|
||||
.insertInto("Province")
|
||||
.columns(["id", "name", "nameEN", "createdBy", "createdAt", "updatedBy", "updatedAt"])
|
||||
.values(r.map((v) => ({ ...v, ...meta })))
|
||||
.onConflict((oc) =>
|
||||
oc.column("id").doUpdateSet({
|
||||
name: (eb) => eb.ref("excluded.name"),
|
||||
nameEN: (eb) => eb.ref("excluded.nameEN"),
|
||||
updatedAt: (eb) => eb.ref("excluded.updatedAt"),
|
||||
}),
|
||||
)
|
||||
.execute();
|
||||
}),
|
||||
);
|
||||
|
||||
await Promise.all(
|
||||
splitChunk(district, 2000, async (r) => {
|
||||
return await tx.$kysely
|
||||
.insertInto("District")
|
||||
.columns([
|
||||
"id",
|
||||
"name",
|
||||
"nameEN",
|
||||
"provinceId",
|
||||
"createdBy",
|
||||
"createdAt",
|
||||
"updatedBy",
|
||||
"updatedAt",
|
||||
])
|
||||
.values(r.map((v) => ({ ...v, ...meta })))
|
||||
.onConflict((oc) =>
|
||||
oc.column("id").doUpdateSet({
|
||||
name: (eb) => eb.ref("excluded.name"),
|
||||
nameEN: (eb) => eb.ref("excluded.nameEN"),
|
||||
provinceId: (eb) => eb.ref("excluded.provinceId"),
|
||||
updatedAt: (eb) => eb.ref("excluded.updatedAt"),
|
||||
}),
|
||||
)
|
||||
.execute();
|
||||
}),
|
||||
);
|
||||
|
||||
await Promise.all(
|
||||
splitChunk(subDistrict, 1000, async (r) => {
|
||||
return await tx.$kysely
|
||||
.insertInto("SubDistrict")
|
||||
.columns([
|
||||
"id",
|
||||
"name",
|
||||
"nameEN",
|
||||
"districtId",
|
||||
"createdBy",
|
||||
"createdAt",
|
||||
"updatedBy",
|
||||
"updatedAt",
|
||||
])
|
||||
.values(r.map((v) => ({ ...v, ...meta })))
|
||||
.onConflict((oc) =>
|
||||
oc.column("id").doUpdateSet({
|
||||
name: (eb) => eb.ref("excluded.name"),
|
||||
nameEN: (eb) => eb.ref("excluded.nameEN"),
|
||||
districtId: (eb) => eb.ref("excluded.districtId"),
|
||||
updatedAt: (eb) => eb.ref("excluded.updatedAt"),
|
||||
}),
|
||||
)
|
||||
.execute();
|
||||
}),
|
||||
);
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue