mirror of
https://github.com/catdevnull/preciazo.git
synced 2024-11-22 14:16:19 +00:00
search
This commit is contained in:
parent
a3bdc59b73
commit
76db90618c
2 changed files with 68 additions and 19 deletions
|
@ -213,6 +213,51 @@ order by fetched_at
|
||||||
|
|
||||||
Json(precios)
|
Json(precios)
|
||||||
}
|
}
|
||||||
|
async fn search(State(pool): State<SqlitePool>, Path(query): Path<String>) -> impl IntoResponse {
|
||||||
|
let sql_query = query
|
||||||
|
.clone()
|
||||||
|
.replace("\"", "\"\"")
|
||||||
|
.split(" ")
|
||||||
|
.map(|x| format!("\"{}\"", x))
|
||||||
|
.join(" ");
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
struct Result {
|
||||||
|
ean: String,
|
||||||
|
name: String,
|
||||||
|
image_url: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
let results = sqlx::query!(
|
||||||
|
"with search_results as (
|
||||||
|
select f.ean from precios_fts f
|
||||||
|
where f.name match ? and f.ean != ''
|
||||||
|
group by f.ean
|
||||||
|
limit 100
|
||||||
|
)
|
||||||
|
select p.id, p.ean, p.name, p.image_url from search_results as s
|
||||||
|
join precios as p
|
||||||
|
on p.ean = s.ean
|
||||||
|
where p.fetched_at = (
|
||||||
|
SELECT MAX(fetched_at)
|
||||||
|
FROM precios as pf
|
||||||
|
WHERE pf.ean = s.ean and pf.name is not null
|
||||||
|
);",
|
||||||
|
sql_query
|
||||||
|
)
|
||||||
|
.fetch_all(&pool)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.into_iter()
|
||||||
|
.map(|r| Result {
|
||||||
|
ean: r.ean,
|
||||||
|
image_url: r.image_url.unwrap(),
|
||||||
|
name: r.name.unwrap(),
|
||||||
|
})
|
||||||
|
.collect_vec();
|
||||||
|
|
||||||
|
Json(results)
|
||||||
|
}
|
||||||
|
|
||||||
async fn get_info(State(pool): State<SqlitePool>) -> impl IntoResponse {
|
async fn get_info(State(pool): State<SqlitePool>) -> impl IntoResponse {
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
|
@ -267,6 +312,7 @@ async fn main() {
|
||||||
.route("/api/0/best-selling-products", get(get_best_selling))
|
.route("/api/0/best-selling-products", get(get_best_selling))
|
||||||
.route("/api/0/ean/:ean/history", get(get_product_history))
|
.route("/api/0/ean/:ean/history", get(get_product_history))
|
||||||
.route("/api/0/info", get(get_info))
|
.route("/api/0/info", get(get_info))
|
||||||
|
.route("/api/0/search/:query", get(search))
|
||||||
.with_state(pool);
|
.with_state(pool);
|
||||||
|
|
||||||
let listener = tokio::net::TcpListener::bind("0.0.0.0:8000").await.unwrap();
|
let listener = tokio::net::TcpListener::bind("0.0.0.0:8000").await.unwrap();
|
||||||
|
|
|
@ -1,26 +1,29 @@
|
||||||
import { sql } from "drizzle-orm";
|
import { z } from "zod";
|
||||||
import type { PageServerLoad } from "./$types";
|
import type { PageServerLoad } from "./$types";
|
||||||
import { getDb } from "$lib/server/db";
|
import { API_HOST } from "$lib";
|
||||||
|
import ky from "ky";
|
||||||
|
|
||||||
|
const zProductResult = z.object({
|
||||||
|
ean: z.string(),
|
||||||
|
name: z.string(),
|
||||||
|
image_url: z.string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
async function search(query: string) {
|
||||||
|
return z
|
||||||
|
.array(zProductResult)
|
||||||
|
.parse(
|
||||||
|
await ky
|
||||||
|
.get(`${API_HOST}/api/0/search/${encodeURIComponent(query)}`)
|
||||||
|
.json(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ url }) => {
|
export const load: PageServerLoad = async ({ url }) => {
|
||||||
const db = await getDb();
|
|
||||||
const query = url.searchParams.get("q");
|
const query = url.searchParams.get("q");
|
||||||
let results: null | { ean: string; name: string; imageUrl: string }[] = null;
|
let results: null | { ean: string; name: string; image_url: string }[] = query
|
||||||
if (query) {
|
? await search(query)
|
||||||
const sQuery = query
|
: null;
|
||||||
.replaceAll(`"`, `""`)
|
|
||||||
.split(" ")
|
|
||||||
.map((s) => `"${s}"`)
|
|
||||||
.join(" ");
|
|
||||||
console.debug(sQuery);
|
|
||||||
const sqlQuery = sql`select p.ean, p.name, p.image_url as imageUrl from precios_fts f
|
|
||||||
join precios p on p.ean = f.ean
|
|
||||||
where f.name match ${sQuery}
|
|
||||||
group by p.ean
|
|
||||||
having max(p.fetched_at)
|
|
||||||
order by p.in_stock desc;`;
|
|
||||||
results = db.all(sqlQuery);
|
|
||||||
}
|
|
||||||
|
|
||||||
return { query, results };
|
return { query, results };
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue