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 {
префикс "#": поиск подстроки в строке, но только среди значений, начинающихся не с латинского или кириллического символа
+
+ префикс "~": поиск по регулярному выражению
+
префикс "?": поиск пустых значений или тех, что начинаются с этого символа