Update how SearchController and searching works
This commit is contained in:
parent
326747c0ce
commit
5ab6d36314
|
@ -11,16 +11,8 @@ const defaultSearchOptions = {
|
||||||
}
|
}
|
||||||
|
|
||||||
class SearchController {
|
class SearchController {
|
||||||
constructor(sequelizeModels, searchTerm, options = defaultSearchOptions) {
|
constructor(sequelizeModels) {
|
||||||
this.models = sequelizeModels;
|
this.models = sequelizeModels;
|
||||||
this.searchTerm = searchTerm;
|
|
||||||
this.searchBy = options.searchBy.replace('title', 'name').replace('author', 'description');
|
|
||||||
this.source = options.source;
|
|
||||||
this.lang = options.language;
|
|
||||||
}
|
|
||||||
|
|
||||||
get hasQuery() {
|
|
||||||
return typeof this.searchTerm !== 'undefined' && this.searchTerm !== '';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get bookReferenceSearchAttributes() {
|
get bookReferenceSearchAttributes() {
|
||||||
|
@ -59,52 +51,58 @@ class SearchController {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async search() {
|
async search(searchTerm, options = defaultSearchOptions) {
|
||||||
const bookReferences = await this.searchReferences();
|
const searchBy = options.searchBy.replace('title', 'name').replace('author', 'description');
|
||||||
|
const { source, language } = options;
|
||||||
|
|
||||||
|
const bookReferences = await this.searchReferences(searchTerm, options);
|
||||||
let searchResults;
|
let searchResults;
|
||||||
switch (this.source) {
|
switch (source) {
|
||||||
case 'openlibrary': {
|
case 'openlibrary': {
|
||||||
searchResults = await this.searchOpenLibrary(this.searchBy);
|
searchResults = await this.searchOpenLibrary(searchBy);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'inventaire':
|
case 'inventaire':
|
||||||
default: {
|
default: {
|
||||||
searchResults = await quickSearchInventaire(this.searchTerm, this.lang);
|
searchResults = await quickSearchInventaire(searchTerm, language);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add any search results that match refs with the same URI and delete from results array
|
// Add any search results that match refs with the same URI and delete from results array
|
||||||
const urisToCheck = searchResults.filter(
|
const urisToCheck = searchResults.filter(
|
||||||
result => !bookReferences.some(ref => result.uri === ref.sources[this.source])
|
result => !bookReferences.some(ref => result.uri === ref.sources[source])
|
||||||
).map(result => result.uri);
|
).map(result => result.uri);
|
||||||
|
|
||||||
|
let extraReferences = [];
|
||||||
if (urisToCheck.length > 0) {
|
if (urisToCheck.length > 0) {
|
||||||
const foundReferences = await this.searchReferencesBySourceCodes(this.source, urisToCheck);
|
extraReferences = await this.searchReferencesBySourceCodes(source, urisToCheck);
|
||||||
|
}
|
||||||
return [
|
return [
|
||||||
...bookReferences,
|
...bookReferences,
|
||||||
...foundReferences,
|
...extraReferences,
|
||||||
...searchResults.filter(result => !urisToCheck.includes(result.uri)),
|
...searchResults.filter( // Only show the rest of the search results
|
||||||
|
result => !extraReferences.some(
|
||||||
|
ref => result.uri === ref.sources[source]
|
||||||
|
)
|
||||||
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
async searchReferences(searchTerm, options = defaultSearchOptions) {
|
||||||
...bookReferences,
|
const searchBy = options.searchBy.replace('title', 'name').replace('author', 'description');
|
||||||
...searchResults.filter(result => result !== null),
|
const { language } = options;
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
async searchReferences() {
|
|
||||||
const { BookReference } = this.models;
|
const { BookReference } = this.models;
|
||||||
|
|
||||||
const exact = await BookReference.findAll({
|
const exact = await BookReference.findAll({
|
||||||
where: {
|
where: {
|
||||||
[Op.and]: [ // All of the contained cases are true
|
[Op.and]: [ // All of the contained cases are true
|
||||||
{
|
{
|
||||||
[this.searchBy]: this.searchTerm, // searchBy is exactly searchTerm
|
[searchBy]: searchTerm, // searchBy is exactly searchTerm
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
locale: this.lang,
|
locale: language,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -122,12 +120,12 @@ class SearchController {
|
||||||
where: {
|
where: {
|
||||||
[Op.and]: [ // All of the contained cases are true
|
[Op.and]: [ // All of the contained cases are true
|
||||||
{
|
{
|
||||||
[this.searchBy]: { // `name` or `description`
|
[searchBy]: { // `name` or `description`
|
||||||
[Op.substring]: this.searchTerm, // LIKE '%searchTerm%'
|
[Op.substring]: searchTerm, // LIKE '%searchTerm%'
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
locale: this.lang,
|
locale: language,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -155,7 +153,7 @@ class SearchController {
|
||||||
|
|
||||||
async searchReferencesBySourceCodes(source, sourceIds) {
|
async searchReferencesBySourceCodes(source, sourceIds) {
|
||||||
const sourceJSONKey = `"${source}"`; // Enable searching withing JSON column.
|
const sourceJSONKey = `"${source}"`; // Enable searching withing JSON column.
|
||||||
return await this.models.BookReference.findOne({
|
return await this.models.BookReference.findAll({
|
||||||
where: {
|
where: {
|
||||||
[Op.or]: sourceIds.map(sourceId => ({
|
[Op.or]: sourceIds.map(sourceId => ({
|
||||||
source: {
|
source: {
|
||||||
|
@ -218,14 +216,14 @@ class SearchController {
|
||||||
}
|
}
|
||||||
|
|
||||||
async searchWikiBooks(term) {
|
async searchWikiBooks(term) {
|
||||||
if (!this.hasQuery) {
|
if (!term) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const query = this.mediaWikiQuery('https://en.wikibooks.org/w/api.php', {
|
const query = this.mediaWikiQuery('https://en.wikibooks.org/w/api.php', {
|
||||||
action: 'query',
|
action: 'query',
|
||||||
list: 'search',
|
list: 'search',
|
||||||
srsearch: this.searchTerm,
|
srsearch: term,
|
||||||
srprop: '',
|
srprop: '',
|
||||||
});
|
});
|
||||||
query(response => {
|
query(response => {
|
||||||
|
@ -257,19 +255,19 @@ class SearchController {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async searchOpenLibrary(searchBy = 'title') {
|
async searchOpenLibrary(searchTerm, searchBy = 'title') {
|
||||||
if (!this.hasQuery) {
|
if (!searchTerm) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
return fetch(`https://openlibrary.org/search.json?${searchBy}=${encodeURIComponent(this.searchTerm)}`)
|
return fetch(`https://openlibrary.org/search.json?${searchBy}=${encodeURIComponent(searchTerm)}`)
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (!response.hasOwnProperty('docs')) {
|
if (!response.hasOwnProperty('docs')) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const booksController = new BooksController('openLibrary', undefined, this.lang);
|
const booksController = new BooksController('openLibrary');
|
||||||
|
|
||||||
// Format the response into usable objects
|
// Format the response into usable objects
|
||||||
const docs = response.docs.map(doc => {
|
const docs = response.docs.map(doc => {
|
||||||
|
|
|
@ -6,9 +6,9 @@ async function routes(fastify, options) {
|
||||||
const searchBy = typeof request.query.by !== 'undefined' ? request.query.by.trim() : 'title';
|
const searchBy = typeof request.query.by !== 'undefined' ? request.query.by.trim() : 'title';
|
||||||
const language = typeof request.query.lang !== 'undefined' ? request.query.lang.trim().split('-')[0] : undefined; // Get base language in cases like 'en-US'
|
const language = typeof request.query.lang !== 'undefined' ? request.query.lang.trim().split('-')[0] : undefined; // Get base language in cases like 'en-US'
|
||||||
const source = typeof request.query.source !== 'undefined' ? request.query.source.trim() : undefined; // Get base language in cases like 'en-US'
|
const source = typeof request.query.source !== 'undefined' ? request.query.source.trim() : undefined; // Get base language in cases like 'en-US'
|
||||||
const controller = new SearchController(fastify.models, searchTerm, { searchBy, source, language });
|
const controller = new SearchController(fastify.models);
|
||||||
|
|
||||||
return await controller.search();
|
return await controller.search(searchTerm, { searchBy, source, language });
|
||||||
});
|
});
|
||||||
|
|
||||||
fastify.get('/api/search/cover', async (request, reply) => {
|
fastify.get('/api/search/cover', async (request, reply) => {
|
||||||
|
|
Loading…
Reference in New Issue