2022-07-07 13:52:01 +03:00
|
|
|
import {Document} from 'flexsearch';
|
2022-07-06 18:09:01 +03:00
|
|
|
import GhostContentAPI from '@tryghost/content-api';
|
2022-07-05 11:09:10 +03:00
|
|
|
|
2022-07-05 12:22:36 +03:00
|
|
|
export default class SearchIndex {
|
2022-07-07 12:09:53 +03:00
|
|
|
constructor({adminUrl, apiKey}) {
|
2022-07-06 18:09:01 +03:00
|
|
|
this.api = new GhostContentAPI({
|
2022-07-07 12:09:53 +03:00
|
|
|
url: adminUrl,
|
2022-07-06 18:09:01 +03:00
|
|
|
key: apiKey,
|
|
|
|
version: 'v5.0'
|
|
|
|
});
|
2022-07-05 11:09:10 +03:00
|
|
|
|
2022-07-07 13:52:01 +03:00
|
|
|
this.postsIndex = new Document({
|
2022-07-07 15:27:00 +03:00
|
|
|
tokenize: 'forward',
|
2022-07-07 13:52:01 +03:00
|
|
|
document: {
|
|
|
|
id: 'id',
|
|
|
|
index: ['title', 'excerpt'],
|
|
|
|
store: true
|
|
|
|
}
|
|
|
|
});
|
|
|
|
this.authorsIndex = new Document({
|
2022-07-07 15:27:00 +03:00
|
|
|
tokenize: 'forward',
|
2022-07-07 13:52:01 +03:00
|
|
|
document: {
|
|
|
|
id: 'id',
|
|
|
|
index: ['name'],
|
|
|
|
store: true
|
|
|
|
}
|
|
|
|
});
|
|
|
|
this.tagsIndex = new Document({
|
2022-07-07 15:27:00 +03:00
|
|
|
tokenize: 'forward',
|
2022-07-07 13:52:01 +03:00
|
|
|
document: {
|
|
|
|
id: 'id',
|
|
|
|
index: ['name'],
|
|
|
|
store: true
|
|
|
|
}
|
|
|
|
});
|
2022-07-05 11:09:10 +03:00
|
|
|
|
2022-07-05 12:22:36 +03:00
|
|
|
this.init = this.init.bind(this);
|
|
|
|
this.search = this.search.bind(this);
|
|
|
|
}
|
2022-07-05 11:09:10 +03:00
|
|
|
|
2022-07-06 18:09:01 +03:00
|
|
|
#updatePostIndex(posts) {
|
|
|
|
posts.forEach((post) => {
|
2022-07-07 13:52:01 +03:00
|
|
|
this.postsIndex.add(post);
|
2022-07-05 11:09:10 +03:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-07-06 18:09:01 +03:00
|
|
|
#updateAuthorsIndex(authors) {
|
|
|
|
authors.forEach((author) => {
|
2022-07-07 13:52:01 +03:00
|
|
|
this.authorsIndex.add(author);
|
2022-07-06 11:37:49 +03:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-07-06 18:09:01 +03:00
|
|
|
#updateTagsIndex(tags) {
|
|
|
|
tags.forEach((tag) => {
|
2022-07-07 13:52:01 +03:00
|
|
|
this.tagsIndex.add(tag);
|
2022-07-06 11:56:16 +03:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-07-05 12:22:36 +03:00
|
|
|
async init() {
|
2022-07-06 18:09:01 +03:00
|
|
|
let posts = await this.api.posts.browse({
|
2022-07-07 13:58:41 +03:00
|
|
|
limit: '10000',
|
2022-07-06 18:09:01 +03:00
|
|
|
fields: 'id,slug,title,excerpt,url,updated_at,visibility',
|
2022-07-07 13:55:08 +03:00
|
|
|
order: 'updated_at DESC'
|
2022-07-06 18:09:01 +03:00
|
|
|
});
|
2022-07-06 12:41:58 +03:00
|
|
|
|
2022-07-06 18:09:01 +03:00
|
|
|
if (posts || posts.length > 0) {
|
|
|
|
if (!posts.length) {
|
|
|
|
posts = [posts];
|
|
|
|
}
|
2022-07-06 12:41:58 +03:00
|
|
|
this.#updatePostIndex(posts);
|
|
|
|
}
|
|
|
|
|
2022-07-06 18:09:01 +03:00
|
|
|
let authors = await this.api.authors.browse({
|
2022-07-07 13:58:41 +03:00
|
|
|
limit: '10000',
|
|
|
|
fields: 'id,slug,name,url,profile_image',
|
|
|
|
order: 'updated_at DESC'
|
2022-07-06 18:09:01 +03:00
|
|
|
});
|
2022-07-06 12:41:58 +03:00
|
|
|
|
2022-07-06 18:09:01 +03:00
|
|
|
if (authors || authors.length > 0) {
|
|
|
|
if (!authors.length) {
|
|
|
|
authors = [authors];
|
|
|
|
}
|
|
|
|
|
2022-07-06 12:41:58 +03:00
|
|
|
this.#updateAuthorsIndex(authors);
|
|
|
|
}
|
|
|
|
|
2022-07-06 18:09:01 +03:00
|
|
|
let tags = await this.api.tags.browse({
|
2022-07-07 13:58:41 +03:00
|
|
|
limit: '10000',
|
|
|
|
fields: 'id,slug,name,url',
|
|
|
|
order: 'updated_at DESC'
|
2022-07-06 18:09:01 +03:00
|
|
|
});
|
2022-07-06 12:41:58 +03:00
|
|
|
|
2022-07-06 18:09:01 +03:00
|
|
|
if (tags || tags.length > 0) {
|
|
|
|
if (!tags.length) {
|
|
|
|
tags = [tags];
|
|
|
|
}
|
|
|
|
|
2022-07-06 12:41:58 +03:00
|
|
|
this.#updateTagsIndex(tags);
|
2022-07-05 12:22:36 +03:00
|
|
|
}
|
2022-07-05 11:09:10 +03:00
|
|
|
}
|
|
|
|
|
2022-07-07 13:52:01 +03:00
|
|
|
#normalizeSearchResult(result) {
|
|
|
|
const normalized = [];
|
|
|
|
const usedIds = {};
|
|
|
|
|
|
|
|
result.forEach((resultItem) => {
|
|
|
|
resultItem.result.forEach((doc) => {
|
|
|
|
if (!usedIds[doc.id]) {
|
|
|
|
normalized.push(doc.doc);
|
|
|
|
usedIds[doc.id] = true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
return normalized;
|
|
|
|
}
|
|
|
|
|
2022-07-05 12:22:36 +03:00
|
|
|
search(value) {
|
2022-07-06 12:26:05 +03:00
|
|
|
const posts = this.postsIndex.search(value, {
|
2022-07-07 13:52:01 +03:00
|
|
|
enrich: true
|
2022-07-06 12:26:05 +03:00
|
|
|
});
|
|
|
|
const authors = this.authorsIndex.search(value, {
|
2022-07-07 13:52:01 +03:00
|
|
|
enrich: true
|
2022-07-06 12:26:05 +03:00
|
|
|
});
|
|
|
|
const tags = this.tagsIndex.search(value, {
|
2022-07-07 13:52:01 +03:00
|
|
|
enrich: true
|
2022-07-06 12:26:05 +03:00
|
|
|
});
|
2022-07-06 11:37:49 +03:00
|
|
|
|
2022-07-05 18:35:07 +03:00
|
|
|
return {
|
2022-07-07 13:52:01 +03:00
|
|
|
posts: this.#normalizeSearchResult(posts),
|
|
|
|
authors: this.#normalizeSearchResult(authors),
|
|
|
|
tags: this.#normalizeSearchResult(tags)
|
2022-07-05 18:35:07 +03:00
|
|
|
};
|
2022-07-05 12:22:36 +03:00
|
|
|
}
|
|
|
|
}
|