diff --git a/src/topics/search.js b/src/topics/search.js new file mode 100644 index 0000000000..e05bd8b084 --- /dev/null +++ b/src/topics/search.js @@ -0,0 +1,49 @@ +'use strict'; + +module.exports = function (Topics) { + Topics.postSearch = async function (data) { + console.log('in topic search'); + console.log('data:', data); + + // extracting the attributes of the data object + const query = data.query || ''; // the search term + const tid = data.tid || 1; // topic id to search in + const page = data.page || 1; // pagination: current page + const uid = data.uid || 0; // user id of the searcher + const paginate = data.hasOwnProperty('paginate') ? data.paginate : true; + + const startTime = process.hrtime(); + + // storing the posts associated with a topic + const set = `tid:${tid}:posts`; + // getting topic attributes using getTopicData + const topicData = await Topics.getTopicData(tid); + // using getTopicPosts function in src/topics/posts.js + // to retrieve all the posts in the topic (by making range 0 to -1) + const postsData = await Topics.getTopicPosts(topicData, set, 0, -1, uid); + + // filtering posts based on query + // looping through retrieved postsData array + // and inspecting each post object for the search query + let filteredPosts = postsData.filter(post => post.content.toLowerCase().includes(query.toLowerCase())); + + const searchResult = { + matchCount: filteredPosts.length, + }; + + if (paginate) { + const resultsPerPage = data.resultsPerPage || 10; // default results per page + const start = Math.max(0, page - 1) * resultsPerPage; + const stop = start + resultsPerPage; + searchResult.pageCount = Math.ceil(filteredPosts.length / resultsPerPage); + filteredPosts = filteredPosts.slice(start, stop); + } + + // timing the search process + searchResult.timing = (process.hrtime(startTime)[1] / 1e6).toFixed(2); // ms timing + + // returning filtered posts and match count + searchResult.posts = filteredPosts; + return searchResult; + }; +}; diff --git a/test/topics.js b/test/topics.js index 8a32e445f5..8d99af493b 100644 --- a/test/topics.js +++ b/test/topics.js @@ -53,6 +53,67 @@ describe('Topic\'s', () => { }; }); + /* describe('.search()', () => { + // let topic; + let adminUid; + + before(async () => { + adminUid = await User.create({ username: 'admin' }); + const categoryObj = await categories.create({ + name: 'Test Category', + description: 'Test category created by testing script', + }); + + topic = { + userId: adminUid, + categoryId: categoryObj.cid, + title: 'Test Topic Title', + content: 'The content of test topic', + }; + + // create a topic first + topic.tid = await topics.create({ + uid: adminUid, + title: topic.title, + content: topic.content, + cid: categoryObj.cid, + }); + + // create posts in the topic for testing + const post1 = await posts.create({ uid: adminUid, tid: topic.tid, content: 'First post in topic' }); + posts.create({ uid: adminUid, tid: topic.tid, content: 'Another post about testing' }); + posts.create({ uid: adminUid, tid: topic.tid, content: 'Post with a different keyword' }); + + // checking if post has been created properly + console.log('post1:', post1); + }); + + it('should return all posts if the query is empty', async () => { + console.log('*****************************'); + // checking if topic and topic.tid created properly + console.log('topic:', topic); + console.log('topic.tid:', topic.tid); + topic.postsearch({ query: '' }, (err, searchData) => { + console.log('searchData:', searchData); + assert.ifError(err); + assert.equal(searchData.matchCount, 3); + assert.equal(searchData.posts.length, 3); + }); + }); + + it('should return all posts matching user query', async () => { + console.log('*****************************'); + console.log('topic:', topic); + console.log('topic.tid:', topic.tid); + topic.postsearch({ query: 'another' }, (err, searchData) => { + console.log('searchData:', searchData); + assert.ifError(err); + assert.equal(searchData.matchCount, 1); + assert.equal(searchData.posts.length, 1); + }); + }); + }); */ + describe('.post', () => { it('should fail to create topic with invalid data', async () => { try {