Улучшение поисковой БД
This commit is contained in:
@@ -11,16 +11,14 @@ class DbCreator {
|
|||||||
async run(db, callback) {
|
async run(db, callback) {
|
||||||
const config = this.config;
|
const config = this.config;
|
||||||
|
|
||||||
//book
|
|
||||||
await db.create({
|
|
||||||
table: 'book'
|
|
||||||
});
|
|
||||||
|
|
||||||
callback({job: 'load inpx', jobMessage: 'Загрузка INPX'});
|
callback({job: 'load inpx', jobMessage: 'Загрузка INPX'});
|
||||||
const readFileCallback = async(readState) => {
|
const readFileCallback = async(readState) => {
|
||||||
callback(readState);
|
callback(readState);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//временная таблица
|
||||||
|
let bookArr = [];
|
||||||
|
|
||||||
//поисковые таблицы, ниже сохраним в БД
|
//поисковые таблицы, ниже сохраним в БД
|
||||||
let authorMap = new Map();//авторы
|
let authorMap = new Map();//авторы
|
||||||
let authorArr = [];
|
let authorArr = [];
|
||||||
@@ -41,7 +39,6 @@ class DbCreator {
|
|||||||
|
|
||||||
//stuff
|
//stuff
|
||||||
let recsLoaded = 0;
|
let recsLoaded = 0;
|
||||||
let id = 0;
|
|
||||||
let chunkNum = 0;
|
let chunkNum = 0;
|
||||||
|
|
||||||
const splitAuthor = (author) => {
|
const splitAuthor = (author) => {
|
||||||
@@ -58,7 +55,8 @@ class DbCreator {
|
|||||||
|
|
||||||
const parsedCallback = async(chunk) => {
|
const parsedCallback = async(chunk) => {
|
||||||
for (const rec of chunk) {
|
for (const rec of chunk) {
|
||||||
rec.id = ++id;
|
const id = bookArr.length;
|
||||||
|
bookArr.push(rec);
|
||||||
|
|
||||||
if (!rec.del) {
|
if (!rec.del) {
|
||||||
bookCount++;
|
bookCount++;
|
||||||
@@ -97,8 +95,6 @@ class DbCreator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await db.insert({table: 'book', rows: chunk});
|
|
||||||
|
|
||||||
recsLoaded += chunk.length;
|
recsLoaded += chunk.length;
|
||||||
callback({recsLoaded});
|
callback({recsLoaded});
|
||||||
|
|
||||||
@@ -117,7 +113,7 @@ class DbCreator {
|
|||||||
callback({job: 'author sort', jobMessage: 'Сортировка'});
|
callback({job: 'author sort', jobMessage: 'Сортировка'});
|
||||||
authorArr.sort((a, b) => a.value.localeCompare(b.value));
|
authorArr.sort((a, b) => a.value.localeCompare(b.value));
|
||||||
|
|
||||||
id = 0;
|
let id = 0;
|
||||||
authorMap = new Map();
|
authorMap = new Map();
|
||||||
for (const authorRec of authorArr) {
|
for (const authorRec of authorArr) {
|
||||||
authorRec.id = ++id;
|
authorRec.id = ++id;
|
||||||
@@ -126,7 +122,6 @@ class DbCreator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
utils.freeMemory();
|
utils.freeMemory();
|
||||||
await db.freeMemory();
|
|
||||||
|
|
||||||
//теперь можно создавать остальные поисковые таблицы
|
//теперь можно создавать остальные поисковые таблицы
|
||||||
const parseField = (fieldValue, fieldMap, fieldArr, authorIds) => {
|
const parseField = (fieldValue, fieldMap, fieldArr, authorIds) => {
|
||||||
@@ -169,10 +164,8 @@ class DbCreator {
|
|||||||
parseField(rec.title, titleMap, titleArr, authorIds);
|
parseField(rec.title, titleMap, titleArr, authorIds);
|
||||||
|
|
||||||
//жанры
|
//жанры
|
||||||
if (!rec.genre)
|
let genre = rec.genre || emptyFieldValue;
|
||||||
rec.genre = emptyFieldValue;
|
genre = rec.genre.split(',');
|
||||||
|
|
||||||
const genre = rec.genre.split(',');
|
|
||||||
|
|
||||||
for (const g of genre) {
|
for (const g of genre) {
|
||||||
let genreRec;
|
let genreRec;
|
||||||
@@ -192,42 +185,57 @@ class DbCreator {
|
|||||||
|
|
||||||
//языки
|
//языки
|
||||||
parseField(rec.lang, langMap, langArr, authorIds);
|
parseField(rec.lang, langMap, langArr, authorIds);
|
||||||
}
|
};
|
||||||
|
|
||||||
callback({job: 'search tables create', jobMessage: 'Создание поисковых таблиц'});
|
const parseBookChunk = async(authorChunk) => {
|
||||||
|
const abRows = [];
|
||||||
//парсинг 2
|
for (const a of authorChunk) {
|
||||||
while (1) {// eslint-disable-line
|
const aBooks = [];
|
||||||
//пробегаемся по сохраненным книгам
|
for (const id of a.bookId) {
|
||||||
const rows = await db.select({
|
const rec = bookArr[id];
|
||||||
table: 'book',
|
|
||||||
where: `
|
|
||||||
let iter = @getItem('book_parsing');
|
|
||||||
if (!iter) {
|
|
||||||
iter = @all();
|
|
||||||
@setItem('book_parsing', iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
const ids = new Set();
|
|
||||||
let id = iter.next();
|
|
||||||
while (!id.done && ids.size < 10000) {
|
|
||||||
ids.add(id.value);
|
|
||||||
id = iter.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
return ids;
|
|
||||||
`
|
|
||||||
});
|
|
||||||
|
|
||||||
if (rows.length) {
|
|
||||||
for (const rec of rows)
|
|
||||||
parseBookRec(rec);
|
parseBookRec(rec);
|
||||||
} else {
|
aBooks.push(rec);
|
||||||
break;
|
}
|
||||||
|
|
||||||
|
abRows.push({id: a.id, author: a.author, books: JSON.stringify(aBooks)});
|
||||||
|
|
||||||
|
delete a.bookId;//в дальнейшем не понадобится, authorArr сохраняем без него
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await db.insert({
|
||||||
|
table: 'author_book',
|
||||||
|
rows: abRows,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
callback({job: 'search tables create', jobMessage: 'Создание поисковых таблиц'});
|
||||||
|
|
||||||
|
//парсинг 2, заполнение посиковых таблиц, сохранение author_book
|
||||||
|
await db.create({
|
||||||
|
table: 'author_book',
|
||||||
|
});
|
||||||
|
|
||||||
|
let idsLen = 0;
|
||||||
|
let aChunk = [];
|
||||||
|
for (const author of authorArr) {// eslint-disable-line
|
||||||
|
aChunk.push(author);
|
||||||
|
idsLen += author.bookId.length;
|
||||||
|
|
||||||
|
if (idsLen > 50000) {
|
||||||
|
await parseBookChunk(aChunk);
|
||||||
|
idsLen = 0;
|
||||||
|
aChunk = [];
|
||||||
|
utils.freeMemory();
|
||||||
|
await db.freeMemory();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (aChunk.length) {
|
||||||
|
await parseBookChunk(aChunk);
|
||||||
|
aChunk = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
//чистка памяти, ибо жрет как не в себя
|
//чистка памяти, ибо жрет как не в себя
|
||||||
|
bookArr = null;
|
||||||
authorMap = null;
|
authorMap = null;
|
||||||
seriesMap = null;
|
seriesMap = null;
|
||||||
titleMap = null;
|
titleMap = null;
|
||||||
@@ -297,23 +305,23 @@ class DbCreator {
|
|||||||
};
|
};
|
||||||
|
|
||||||
//author
|
//author
|
||||||
callback({job: 'author save', jobMessage: 'Сохранение авторов книг'});
|
callback({job: 'author save', jobMessage: 'Сохранение индекса авторов'});
|
||||||
await saveTable('author', authorArr, () => {authorArr = null}, false);
|
await saveTable('author', authorArr, () => {authorArr = null}, false);
|
||||||
|
|
||||||
//series
|
//series
|
||||||
callback({job: 'series save', jobMessage: 'Сохранение серий книг'});
|
callback({job: 'series save', jobMessage: 'Сохранение индекса серий'});
|
||||||
await saveTable('series', seriesArr, () => {seriesArr = null});
|
await saveTable('series', seriesArr, () => {seriesArr = null});
|
||||||
|
|
||||||
//title
|
//title
|
||||||
callback({job: 'title save', jobMessage: 'Сохранение названий книг'});
|
callback({job: 'title save', jobMessage: 'Сохранение индекса названий'});
|
||||||
await saveTable('title', titleArr, () => {titleArr = null});
|
await saveTable('title', titleArr, () => {titleArr = null});
|
||||||
|
|
||||||
//genre
|
//genre
|
||||||
callback({job: 'genre save', jobMessage: 'Сохранение жанров'});
|
callback({job: 'genre save', jobMessage: 'Сохранение индекса жанров'});
|
||||||
await saveTable('genre', genreArr, () => {genreArr = null});
|
await saveTable('genre', genreArr, () => {genreArr = null});
|
||||||
|
|
||||||
//lang
|
//lang
|
||||||
callback({job: 'lang save', jobMessage: 'Сохранение языков'});
|
callback({job: 'lang save', jobMessage: 'Сохранение индекса языков'});
|
||||||
await saveTable('lang', langArr, () => {langArr = null});
|
await saveTable('lang', langArr, () => {langArr = null});
|
||||||
|
|
||||||
//кэш-таблицы запросов
|
//кэш-таблицы запросов
|
||||||
|
|||||||
@@ -289,8 +289,7 @@ class DbSearcher {
|
|||||||
|
|
||||||
//выборка автора по authorId
|
//выборка автора по authorId
|
||||||
const rows = await db.select({
|
const rows = await db.select({
|
||||||
table: 'author',
|
table: 'author_book',
|
||||||
map: `(r) => ({author: r.author, bookId: r.bookId})`,
|
|
||||||
where: `@@id(${db.esc(authorId)})`
|
where: `@@id(${db.esc(authorId)})`
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -299,13 +298,7 @@ class DbSearcher {
|
|||||||
|
|
||||||
if (rows.length) {
|
if (rows.length) {
|
||||||
author = rows[0].author;
|
author = rows[0].author;
|
||||||
|
books = rows[0].books;
|
||||||
//выборка книг по bookId
|
|
||||||
books = await db.select({
|
|
||||||
table: 'book',
|
|
||||||
//map: `(r) => ({})`,
|
|
||||||
where: `@@id(${db.esc(rows[0].bookId)})`,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result = {author, books};
|
result = {author, books};
|
||||||
|
|||||||
Reference in New Issue
Block a user