feat: search working as expected

This commit is contained in:
Daniel Avila 2023-03-18 17:49:24 -04:00
parent da42d6272a
commit 4197a92609
5 changed files with 60 additions and 51 deletions

View file

@ -59,7 +59,7 @@ convoSchema.plugin(mongoMeili, {
host: process.env.MEILI_HOST, host: process.env.MEILI_HOST,
apiKey: process.env.MEILI_KEY, apiKey: process.env.MEILI_KEY,
indexName: 'convos', // Will get created automatically if it doesn't exist already indexName: 'convos', // Will get created automatically if it doesn't exist already
primaryKey: 'conversationId', primaryKey: 'conversationId'
}); });
const Conversation = const Conversation =
@ -142,15 +142,40 @@ module.exports = {
return { conversations: [], pages: 1, pageNumber, pageSize }; return { conversations: [], pages: 1, pageNumber, pageSize };
} }
const promises = convoIds.map(convo => { const cache = {};
return Conversation.findOne({ user, conversationId: convo.conversationId}).exec(); const promises = [];
convoIds.forEach((convo, i) => {
const page = Math.floor(i / pageSize) + 1;
if (!cache[page]) {
cache[page] = [];
}
const conversation = Conversation.findOne({
user,
conversationId: convo.conversationId
}).exec();
cache[page].push(conversation);
promises.push(conversation);
}); });
const results = (await Promise.all(promises)).filter(convo => convo); const results = (await Promise.all(promises)).filter((convo) => convo);
const startIndex = (pageNumber - 1) * pageSize; for (const key in cache) {
const convos = results.slice(startIndex, startIndex + pageSize); const promises = cache[key];
cache[key] = (await Promise.all(promises)).filter((convo) => convo);
}
// const startIndex = (pageNumber - 1) * pageSize;
// const convos = results.slice(startIndex, startIndex + pageSize);
const totalPages = Math.ceil(results.length / pageSize); const totalPages = Math.ceil(results.length / pageSize);
console.log(results.length, totalPages, convos.length); cache.pages = totalPages;
return { conversations: convos, pages: totalPages, pageNumber, pageSize }; cache.pageSize = pageSize;
return {
cache,
conversations: cache[pageNumber],
pages: totalPages,
pageNumber,
pageSize
};
} catch (error) { } catch (error) {
console.log(error); console.log(error);
return { message: 'Error fetching conversations' }; return { message: 'Error fetching conversations' };

View file

@ -4,6 +4,7 @@ const { Message } = require('../../models/Message');
const { Conversation, getConvosQueried } = require('../../models/Conversation'); const { Conversation, getConvosQueried } = require('../../models/Conversation');
const { reduceMessages, reduceHits } = require('../../lib/utils/reduceHits'); const { reduceMessages, reduceHits } = require('../../lib/utils/reduceHits');
// const { MeiliSearch } = require('meilisearch'); // const { MeiliSearch } = require('meilisearch');
const cache = new Map();
router.get('/sync', async function (req, res) { router.get('/sync', async function (req, res) {
await Message.syncWithMeili(); await Message.syncWithMeili();
@ -13,18 +14,26 @@ router.get('/sync', async function (req, res) {
router.get('/', async function (req, res) { router.get('/', async function (req, res) {
try { try {
const user = req?.session?.user?.username;
const { q } = req.query; const { q } = req.query;
console.log(req.query, req.params);
const pageNumber = req.query.pageNumber || 1; const pageNumber = req.query.pageNumber || 1;
const key = `${user || ''}${q}`;
if (cache.has(key)) {
console.log('cache hit', key);
const cached = cache.get(key);
const { pages, pageSize } = cached;
res.status(200).send({ conversations: cached[pageNumber], pages, pageNumber, pageSize });
return;
} else {
cache.clear();
}
const message = await Message.meiliSearch(q); const message = await Message.meiliSearch(q);
const title = await Conversation.meiliSearch(q, { attributesToHighlight: ['title'] }); const title = await Conversation.meiliSearch(q, { attributesToHighlight: ['title'] });
const sortedHits = reduceHits(message.hits, title.hits); const sortedHits = reduceHits(message.hits, title.hits);
const result = await getConvosQueried( const result = await getConvosQueried(user, sortedHits, pageNumber);
req?.session?.user?.username, cache.set(q, result.cache);
sortedHits, delete result.cache;
pageNumber
);
console.log('result', result.pageNumber, result.pages, result.pageSize);
res.status(200).send(result); res.status(200).send(result);
} catch (error) { } catch (error) {
console.log(error); console.log(error);

View file

@ -3,31 +3,15 @@ import { debounce } from 'lodash';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { Search } from 'lucide-react'; import { Search } from 'lucide-react';
import { setQuery } from '~/store/searchSlice'; import { setQuery } from '~/store/searchSlice';
import { setConvos, refreshConversation } from '~/store/convoSlice';
import axios from 'axios';
// const fetch = async (q, pageNumber, callback) => { export default function SearchBar({ fetch, clearSearch }) {
// const { data } = await axios.get(`/api/search?q=${q}&pageNumber=${pageNumber}`);
// console.log(data);
// callback(data);
// };
export default function SearchBar({ fetch, onSuccess, clearSearch }) {
const dispatch = useDispatch(); const dispatch = useDispatch();
const [inputValue, setInputValue] = useState(''); const [inputValue, setInputValue] = useState('');
// const onSuccess = (data) => {
// const { conversations, pages, pageNumber } = data;
// dispatch(setConvos({ convos: conversations, searchFetch: true }));
// dispatch(setPage(pageNumber));
// dispatch(setPages(pages));
// };
const debouncedChangeHandler = useCallback( const debouncedChangeHandler = useCallback(
debounce((q) => { debounce((q) => {
dispatch(setQuery(q)); dispatch(setQuery(q));
if (q.length > 0) { if (q.length > 0) {
// fetch(q, 1, onSuccess);
fetch(q, 1); fetch(q, 1);
} }
}, 750), }, 750),
@ -46,19 +30,12 @@ export default function SearchBar({ fetch, onSuccess, clearSearch }) {
const changeHandler = (e) => { const changeHandler = (e) => {
// if (!search) {
// console.log('setting page to 1');
// dispatch(setPage(1));
// }
let q = e.target.value; let q = e.target.value;
setInputValue(q); setInputValue(q);
q = q.trim(); q = q.trim();
if (q === '') { if (q === '') {
dispatch(setQuery('')); dispatch(setQuery(''));
// dispatch(setPage(1));
// dispatch(refreshConversation());
clearSearch(); clearSearch();
} else { } else {
debouncedChangeHandler(q); debouncedChangeHandler(q);

View file

@ -6,17 +6,10 @@ import Spinner from '../svg/Spinner';
import Pages from '../Conversations/Pages'; import Pages from '../Conversations/Pages';
import Conversations from '../Conversations'; import Conversations from '../Conversations';
import NavLinks from './NavLinks'; import NavLinks from './NavLinks';
import { swr } from '~/utils/fetchers'; import { searchFetcher, swr } from '~/utils/fetchers';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { setConvos, refreshConversation } from '~/store/convoSlice'; import { setConvos, refreshConversation } from '~/store/convoSlice';
const fetcher = async (pre, q, pageNumber, callback) => {
pre();
const { data } = await axios.get(`/api/search?q=${q}&pageNumber=${pageNumber}`);
console.log(data);
callback(data);
};
export default function Nav({ navVisible, setNavVisible }) { export default function Nav({ navVisible, setNavVisible }) {
const dispatch = useDispatch(); const dispatch = useDispatch();
const [isHovering, setIsHovering] = useState(false); const [isHovering, setIsHovering] = useState(false);
@ -51,7 +44,7 @@ export default function Nav({ navVisible, setNavVisible }) {
setIsFetching(false); setIsFetching(false);
}; };
const fetch = useCallback(_.partialRight(fetcher.bind(null, () => setIsFetching(true)), onSearchSuccess), [dispatch]); const fetch = useCallback(_.partialRight(searchFetcher.bind(null, () => setIsFetching(true)), onSearchSuccess), [dispatch]);
const clearSearch = () => { const clearSearch = () => {
setPage(1); setPage(1);
@ -79,7 +72,6 @@ export default function Nav({ navVisible, setNavVisible }) {
setPage((prev) => prev + 1); setPage((prev) => prev + 1);
await mutate(); await mutate();
} else { } else {
// await fetch(query, +pageNumber + 1, onSearchSuccess);
await fetch(query, +pageNumber + 1); await fetch(query, +pageNumber + 1);
} }
}; };
@ -91,7 +83,6 @@ export default function Nav({ navVisible, setNavVisible }) {
setPage((prev) => prev - 1); setPage((prev) => prev - 1);
await mutate(); await mutate();
} else { } else {
// await fetch(query, +pageNumber - 1, onSearchSuccess);
await fetch(query, +pageNumber - 1); await fetch(query, +pageNumber - 1);
} }
}; };
@ -111,7 +102,7 @@ export default function Nav({ navVisible, setNavVisible }) {
container.scrollTop = Math.min(maxScrollTop, scrollPositionRef.current); container.scrollTop = Math.min(maxScrollTop, scrollPositionRef.current);
} }
}, [data]); }, [data, convos]);
useEffect(() => { useEffect(() => {
setNavVisible(false); setNavVisible(false);

View file

@ -13,6 +13,13 @@ const postRequest = async (url, { arg }) => {
return await axios.post(url, { withCredentials: true, arg }); return await axios.post(url, { withCredentials: true, arg });
}; };
export const searchFetcher = async (pre, q, pageNumber, callback) => {
pre();
const { data } = await axios.get(`/api/search?q=${q}&pageNumber=${pageNumber}`);
console.log('search data', data);
callback(data);
};
export const swr = (path, successCallback, options) => { export const swr = (path, successCallback, options) => {
const _options = { ...options }; const _options = { ...options };