From 491c2f34066f473c7cdda32d0f7631d2e05b13bb Mon Sep 17 00:00:00 2001 From: Book Pauk Date: Wed, 26 Oct 2022 17:50:48 +0700 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20titleSearch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/components/Api/Api.vue | 4 + server/controllers/WebSocketController.js | 14 ++++ server/core/DbSearcher.js | 89 +++++++++++++++++++++++ server/core/WebWorker.js | 13 ++++ 4 files changed, 120 insertions(+) diff --git a/client/components/Api/Api.vue b/client/components/Api/Api.vue index 742eecc..f055296 100644 --- a/client/components/Api/Api.vue +++ b/client/components/Api/Api.vue @@ -214,6 +214,10 @@ class Api { return await this.request({action: 'series-search', query}); } + async titleSearch(query) { + return await this.request({action: 'title-search', query}); + } + async getAuthorBookList(authorId) { return await this.request({action: 'get-author-book-list', authorId}); } diff --git a/server/controllers/WebSocketController.js b/server/controllers/WebSocketController.js index 7ff4f9f..53d9735 100644 --- a/server/controllers/WebSocketController.js +++ b/server/controllers/WebSocketController.js @@ -78,6 +78,8 @@ class WebSocketController { await this.authorSearch(req, ws); break; case 'series-search': await this.seriesSearch(req, ws); break; + case 'title-search': + await this.titleSearch(req, ws); break; case 'get-author-book-list': await this.getAuthorBookList(req, ws); break; case 'get-series-book-list': @@ -156,6 +158,18 @@ class WebSocketController { this.send(result, req, ws); } + async titleSearch(req, ws) { + if (!this.config.extendedSearch) + throw new Error(`Extended search disabled`); + + if (!req.query) + throw new Error(`query is empty`); + + const result = await this.webWorker.titleSearch(req.query); + + this.send(result, req, ws); + } + async getAuthorBookList(req, ws) { const result = await this.webWorker.getAuthorBookList(req.authorId); diff --git a/server/core/DbSearcher.js b/server/core/DbSearcher.js index d9ad814..26a915d 100644 --- a/server/core/DbSearcher.js +++ b/server/core/DbSearcher.js @@ -513,6 +513,58 @@ class DbSearcher { return seriesIds; } + async selectTitleIds(query) { + const db = this.db; + + let titleIds = false; + let isAll = !(query.title && query.title !== '*'); + + //серии + const titleKеy = `title-ids-title-${query.title}`; + titleIds = await this.getCached(titleKеy); + + if (titleIds === null) { + if (query.title && query.title !== '*') { + const where = this.getWhere(query.title); + + const seriesRows = await db.select({ + table: 'title', + rawResult: true, + where: `return Array.from(${where})`, + }); + + titleIds = seriesRows[0].rawResult; + } else { + const seriesRows = await db.select({ + table: 'title', + rawResult: true, + where: `return Array.from(@all())`, + }); + + titleIds = seriesRows[0].rawResult; + } + + titleIds.sort((a, b) => a - b); + + await this.putCached(titleKеy, titleIds); + } + + const where = this.getWhere2(query, (isAll ? false : titleIds), 'title'); + + if (where) { + //тяжелый запрос перебором в series_book + const rows = await db.select({ + table: 'title_book', + rawResult: true, + where, + }); + + titleIds = rows[0].rawResult; + } + + return titleIds; + } + queryKey(q) { return JSON.stringify([q.author, q.series, q.title, q.genre, q.lang]); } @@ -663,6 +715,43 @@ class DbSearcher { } } + async titleSearch(query) { + if (this.closed) + throw new Error('DbSearcher closed'); + + this.searchFlag++; + + try { + const db = this.db; + + const key = `title-ids-${this.queryKey(query)}`; + + //сначала попробуем найти в кеше + let seriesIds = await this.getCached(key); + if (seriesIds === null) {//не нашли в кеше, ищем в поисковых таблицах + seriesIds = await this.selectTitleIds(query); + + await this.putCached(key, seriesIds); + } + + const totalFound = seriesIds.length; + let limit = (query.limit ? query.limit : 100); + limit = (limit > maxLimit ? maxLimit : limit); + const offset = (query.offset ? query.offset : 0); + + //выборка найденных авторов + const result = await db.select({ + table: 'title_book', + map: `(r) => ({id: r.id, series: r.series, bookCount: r.bookCount, bookDelCount: r.bookDelCount})`, + where: `@@id(${db.esc(seriesIds.slice(offset, offset + limit))})` + }); + + return {result, totalFound}; + } finally { + this.searchFlag--; + } + } + async getAuthorBookList(authorId) { if (this.closed) throw new Error('DbSearcher closed'); diff --git a/server/core/WebWorker.js b/server/core/WebWorker.js index 42338cd..e506f10 100644 --- a/server/core/WebWorker.js +++ b/server/core/WebWorker.js @@ -274,6 +274,19 @@ class WebWorker { }; } + async titleSearch(query) { + this.checkMyState(); + + const config = await this.dbConfig(); + const result = await this.dbSearcher.titleSearch(query); + + return { + title: result.result, + totalFound: result.totalFound, + inpxHash: (config.inpxHash ? config.inpxHash : ''), + }; + } + async getAuthorBookList(authorId) { this.checkMyState();