2022-07-05 11:09:10 +03:00
|
|
|
import elasticlunr from 'elasticlunr';
|
|
|
|
|
2022-07-05 12:22:36 +03:00
|
|
|
export default class SearchIndex {
|
2022-07-06 12:41:58 +03:00
|
|
|
constructor({apiUrl, apiKey}) {
|
2022-07-05 12:22:36 +03:00
|
|
|
this.apiUrl = apiUrl;
|
|
|
|
this.apiKey = apiKey;
|
2022-07-05 11:09:10 +03:00
|
|
|
|
2022-07-05 18:35:07 +03:00
|
|
|
this.postsIndex = null;
|
2022-07-06 11:37:49 +03:00
|
|
|
this.authorsIndex = null;
|
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 11:37:49 +03:00
|
|
|
#updatePostIndex(data) {
|
2022-07-05 12:22:36 +03:00
|
|
|
data.posts.forEach((post) => {
|
2022-07-05 18:35:07 +03:00
|
|
|
this.postsIndex.addDoc({
|
2022-07-05 17:38:29 +03:00
|
|
|
id: post.id,
|
|
|
|
title: post.title,
|
2022-07-05 18:34:31 +03:00
|
|
|
excerpt: post.excerpt,
|
2022-07-06 13:29:48 +03:00
|
|
|
slug: post.slug,
|
|
|
|
url: post.url
|
2022-07-05 17:38:29 +03:00
|
|
|
});
|
2022-07-05 11:09:10 +03:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-07-06 11:37:49 +03:00
|
|
|
#updateAuthorsIndex(data) {
|
|
|
|
data.authors.forEach((author) => {
|
|
|
|
this.authorsIndex.addDoc({
|
|
|
|
id: author.id,
|
2022-07-06 13:29:48 +03:00
|
|
|
name: author.name,
|
|
|
|
url: author.url
|
2022-07-06 11:37:49 +03:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-07-06 11:56:16 +03:00
|
|
|
#updateTagsIndex(data) {
|
|
|
|
data.tags.forEach((tag) => {
|
|
|
|
this.tagsIndex.addDoc({
|
|
|
|
id: tag.id,
|
2022-07-06 13:29:48 +03:00
|
|
|
name: tag.name,
|
|
|
|
url: tag.url
|
2022-07-06 11:56:16 +03:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-07-05 12:22:36 +03:00
|
|
|
async init() {
|
|
|
|
// remove default stop words to search of *any* word
|
|
|
|
elasticlunr.clearStopWords();
|
|
|
|
|
2022-07-06 11:37:49 +03:00
|
|
|
const postsAPIUrl = `${this.apiUrl}/posts/?key=${this.apiKey}&limit=all&fields=id,slug,title,excerpt,url,updated_at,visibility&order=updated_at%20desc&formats=plaintext`;
|
2022-07-06 12:26:05 +03:00
|
|
|
const authorsAPIUrl = `${this.apiUrl}/authors/?key=${this.apiKey}&limit=all&fields=id,slug,name,url,profile_image`;
|
2022-07-06 11:56:16 +03:00
|
|
|
const tagsAPIUrl = `${this.apiUrl}/tags/?key=${this.apiKey}&limit=all&fields=id,slug,name,url`;
|
2022-07-05 12:22:36 +03:00
|
|
|
|
2022-07-06 12:41:58 +03:00
|
|
|
const postsResponse = await fetch(postsAPIUrl);
|
|
|
|
const posts = await postsResponse.json();
|
|
|
|
|
|
|
|
this.postsIndex = elasticlunr();
|
|
|
|
this.postsIndex.addField('title');
|
|
|
|
this.postsIndex.addField('url');
|
|
|
|
this.postsIndex.addField('excerpt');
|
|
|
|
this.postsIndex.setRef('id');
|
|
|
|
|
|
|
|
if (posts.posts.length > 0) {
|
|
|
|
this.#updatePostIndex(posts);
|
|
|
|
}
|
|
|
|
|
|
|
|
const authorsResponse = await fetch(authorsAPIUrl);
|
|
|
|
const authors = await authorsResponse.json();
|
|
|
|
|
|
|
|
this.authorsIndex = elasticlunr();
|
|
|
|
this.authorsIndex.addField('name');
|
|
|
|
this.authorsIndex.addField('url');
|
|
|
|
this.authorsIndex.setRef('id');
|
|
|
|
|
|
|
|
if (authors.authors.length > 0) {
|
|
|
|
this.#updateAuthorsIndex(authors);
|
|
|
|
}
|
|
|
|
|
|
|
|
const tagsResponse = await fetch(tagsAPIUrl);
|
|
|
|
const tags = await tagsResponse.json();
|
|
|
|
|
|
|
|
this.tagsIndex = elasticlunr();
|
|
|
|
this.tagsIndex.addField('name');
|
|
|
|
this.tagsIndex.addField('url');
|
|
|
|
this.tagsIndex.setRef('id');
|
|
|
|
|
|
|
|
if (tags.tags.length > 0) {
|
|
|
|
this.#updateTagsIndex(tags);
|
2022-07-05 12:22:36 +03:00
|
|
|
}
|
2022-07-05 11:09:10 +03:00
|
|
|
}
|
|
|
|
|
2022-07-05 12:22:36 +03:00
|
|
|
search(value) {
|
2022-07-06 12:26:05 +03:00
|
|
|
const posts = this.postsIndex.search(value, {
|
|
|
|
fields: {
|
|
|
|
title: {boost: 1},
|
|
|
|
excerpt: {boost: 1}
|
|
|
|
},
|
|
|
|
expand: true
|
|
|
|
});
|
|
|
|
const authors = this.authorsIndex.search(value, {
|
|
|
|
fields: {
|
|
|
|
name: {boost: 1}
|
|
|
|
},
|
|
|
|
expand: true
|
|
|
|
});
|
|
|
|
const tags = this.tagsIndex.search(value, {
|
|
|
|
fields: {
|
|
|
|
name: {boost: 1}
|
|
|
|
},
|
|
|
|
expand: true
|
|
|
|
});
|
2022-07-06 11:37:49 +03:00
|
|
|
|
2022-07-05 18:35:07 +03:00
|
|
|
return {
|
|
|
|
posts: posts.map((doc) => {
|
|
|
|
return this.postsIndex.documentStore.docs[doc.ref];
|
2022-07-06 11:37:49 +03:00
|
|
|
}),
|
|
|
|
authors: authors.map((doc) => {
|
|
|
|
return this.authorsIndex.documentStore.docs[doc.ref];
|
2022-07-06 11:56:16 +03:00
|
|
|
}),
|
|
|
|
tags: tags.map((doc) => {
|
|
|
|
return this.tagsIndex.documentStore.docs[doc.ref];
|
2022-07-05 18:35:07 +03:00
|
|
|
})
|
|
|
|
};
|
2022-07-05 12:22:36 +03:00
|
|
|
}
|
|
|
|
}
|