diff --git a/client/components/Search/BaseList.js b/client/components/Search/BaseList.js index dee8119..0a8113f 100644 --- a/client/components/Search/BaseList.js +++ b/client/components/Search/BaseList.js @@ -385,7 +385,14 @@ export default class BaseList { } else if (searchValue[0] == '#') { searchValue = searchValue.substring(1); - return !bookValue || (bookValue !== emptyFieldValue && !enru.has(bookValue[0]) && bookValue.indexOf(searchValue) >= 0); + if (!bookValue) + return false; + return bookValue !== emptyFieldValue && !enru.has(bookValue[0]) && bookValue.indexOf(searchValue) >= 0; + } else if (searchValue[0] == '~') {//RegExp + + searchValue = searchValue.substring(1); + const re = new RegExp(searchValue, 'gi'); + return re.exec(bookValue); } else { //where = `@dirtyIndexLR('value', ${db.esc(a)}, ${db.esc(a + maxUtf8Char)})`; return bookValue.localeCompare(searchValue) >= 0 && bookValue.localeCompare(searchValue + maxUtf8Char) <= 0; diff --git a/client/components/Search/Search.vue b/client/components/Search/Search.vue index 05309bc..c0b563e 100644 --- a/client/components/Search/Search.vue +++ b/client/components/Search/Search.vue @@ -789,6 +789,11 @@ class Search { Указание простого "#" в поиске по названию означает: найти всех авторов, названия книг которых начинаются не с русской или латинской буквы
+
  • + "~" поиск по регулярному выражению. Например, для "~^\\s" в поле названия, будут найдены + все книги, названия которых начинаются с пробельного символа +
  • +
  • "?" поиск пустых значений или тех, что начинаются с этого символа. Например, "?" в поле серии означает: найти всех авторов, у которых есть книги без серий или название серии начинается с "?". diff --git a/client/components/Search/SelectExtSearchDialog/SelectExtSearchDialog.vue b/client/components/Search/SelectExtSearchDialog/SelectExtSearchDialog.vue index b4fe73d..197a9db 100644 --- a/client/components/Search/SelectExtSearchDialog/SelectExtSearchDialog.vue +++ b/client/components/Search/SelectExtSearchDialog/SelectExtSearchDialog.vue @@ -160,6 +160,9 @@ class SelectExtSearchDialog {
  • префикс "#": поиск подстроки в строке, но только среди начинающихся не с латинского или кириллического символа
  • +
  • + префикс "~": поиск по регулярному выражению +
  • префикс "?": поиск пустых значений или тех, что начинаются с этого символа
  • diff --git a/server/core/DbSearcher.js b/server/core/DbSearcher.js index 49c7b48..69697a4 100644 --- a/server/core/DbSearcher.js +++ b/server/core/DbSearcher.js @@ -63,8 +63,18 @@ class DbSearcher { a = a.substring(1); where = `@indexIter('value', (v) => { const enru = new Set(${db.esc(enruArr)}); - return !v || (v !== ${db.esc(emptyFieldValue)} && !enru.has(v[0]) && v.indexOf(${db.esc(a)}) >= 0); + if (!v) + return false; + return v !== ${db.esc(emptyFieldValue)} && !enru.has(v[0]) && v.indexOf(${db.esc(a)}) >= 0; })`; + } else if (a[0] == '~') {//RegExp + a = a.substring(1); + where = ` + await (async() => { + const re = new RegExp(${db.esc(a)}, 'gi'); + @@indexIter('value', (v) => re.exec(v) ); + })() + `; } else { where = `@dirtyIndexLR('value', ${db.esc(a)}, ${db.esc(a + maxUtf8Char)})`; } @@ -99,7 +109,7 @@ class DbSearcher { }; //авторы - if (query.author && query.author !== '*') { + if (query.author) { const key = `book-ids-author-${query.author}`; let ids = await this.getCached(key); @@ -113,7 +123,7 @@ class DbSearcher { } //серии - if (query.series && query.series !== '*') { + if (query.series) { const key = `book-ids-series-${query.series}`; let ids = await this.getCached(key); @@ -127,7 +137,7 @@ class DbSearcher { } //названия - if (query.title && query.title !== '*') { + if (query.title) { const key = `book-ids-title-${query.title}`; let ids = await this.getCached(key); @@ -337,7 +347,7 @@ class DbSearcher { //то в выборку по bookId могут попасть авторы, которые отсутствуют в критерии query.author, //поэтому дополнительно фильтруем let result = null; - if (from == 'author' && query.author && query.author !== '*') { + if (from == 'author' && query.author) { const key = `filter-ids-author-${query.author}`; let authorIds = await this.getCached(key); @@ -562,6 +572,15 @@ class DbSearcher { searchValue = searchValue.substring(1); return `(row.${bookField} === '' || (!enru.has(row.${bookField}.toLowerCase()[0]) && row.${bookField}.toLowerCase().indexOf(${db.esc(searchValue)}) >= 0))`; + } else if (searchValue[0] == '~') {//RegExp + searchValue = searchValue.substring(1); + + return ` + (() => { + const re = new RegExp(${db.esc(searchValue)}, 'gi'); + return re.exec(row.${bookField}); + })() + `; } else { return `(row.${bookField}.toLowerCase().localeCompare(${db.esc(searchValue)}) >= 0 ` + diff --git a/server/core/opds/BasePage.js b/server/core/opds/BasePage.js index ccfc4dc..fba01bb 100644 --- a/server/core/opds/BasePage.js +++ b/server/core/opds/BasePage.js @@ -250,7 +250,14 @@ class BasePage { } else if (searchValue[0] == '#') { searchValue = searchValue.substring(1); - return !bookValue || (bookValue !== emptyFieldValue && !enru.has(bookValue[0]) && bookValue.indexOf(searchValue) >= 0); + if (!bookValue) + return false; + return bookValue !== emptyFieldValue && !enru.has(bookValue[0]) && bookValue.indexOf(searchValue) >= 0; + } else if (searchValue[0] == '~') {//RegExp + + searchValue = searchValue.substring(1); + const re = new RegExp(searchValue, 'gi'); + return re.exec(bookValue); } else { //where = `@dirtyIndexLR('value', ${db.esc(a)}, ${db.esc(a + maxUtf8Char)})`; return bookValue.localeCompare(searchValue) >= 0 && bookValue.localeCompare(searchValue + maxUtf8Char) <= 0; diff --git a/server/core/opds/SearchHelpPage.js b/server/core/opds/SearchHelpPage.js index 5c71751..60c084a 100644 --- a/server/core/opds/SearchHelpPage.js +++ b/server/core/opds/SearchHelpPage.js @@ -31,6 +31,9 @@ class SearchHelpPage extends BasePage {
  • префикс "#": поиск подстроки в строке, но только среди значений, начинающихся не с латинского или кириллического символа
  • +
  • + префикс "~": поиск по регулярному выражению +
  • префикс "?": поиск пустых значений или тех, что начинаются с этого символа