Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

544 configure meilisearch #561

Merged
merged 12 commits into from
Jun 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion projects/bp-gallery/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@
"jodit-react": "^1.3.31",
"leaflet": "^1.9.3",
"lodash": "^4.17.21",
"meilisearch": "^0.33.0",
"nanoid": "^4.0.2",
"node-sass": "^8.0.0",
"puppeteer": "^19.4.0",
"react-currency-input-field": "^3.6.10",
"react": "^18.2.0",
"react-currency-input-field": "^3.6.10",
"react-date-range": "^1.4.0",
"react-device-detect": "^2.2.2",
"react-dom": "^18.2.0",
Expand Down
46 changes: 22 additions & 24 deletions projects/bp-gallery/src/components/views/search/SearchView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,8 @@ import SearchBreadcrumbs from './SearchBreadcrumbs';
import SearchHub from './SearchHub';
import './SearchView.scss';
import { isValidYear } from './helpers/addNewParamToSearchPath';
import {
SearchType,
convertSearchParamsToPictureFilters,
paramToTime,
} from './helpers/search-filters';
import getSearchResultPictureIds from './helpers/getSearchResultPictureIds';
import { SearchType, paramToTime } from './helpers/search-filters';
import { toURLSearchParam } from './helpers/url-search-params';

const isValidTimeSpecification = (searchRequest: string) => {
Expand Down Expand Up @@ -47,25 +44,26 @@ const SearchView = () => {

// Builds query from search params in the path
const queryParams = useMemo(() => {
if (isAllSearchActive) {
const allSearchTerms = searchParams
.getAll(toURLSearchParam(SearchType.ALL))
.map(decodeURIComponent);
const searchTimes: string[][] = [];
allSearchTerms.forEach(searchTerm => {
if (isValidTimeSpecification(searchTerm)) {
const { startTime, endTime } = paramToTime(searchTerm);
searchTimes.push([searchTerm, startTime, endTime]);
}
});
return {
searchTerms: allSearchTerms.filter(searchTerm => !isValidTimeSpecification(searchTerm)),
searchTimes,
};
}
return convertSearchParamsToPictureFilters(searchParams);
}, [isAllSearchActive, searchParams]);

// if (isAllSearchActive) {
MariusDoe marked this conversation as resolved.
Show resolved Hide resolved
const allSearchTerms = searchParams
.getAll(toURLSearchParam(SearchType.ALL))
.map(decodeURIComponent);
const searchTimes: string[][] = [];
allSearchTerms.forEach(searchTerm => {
if (isValidTimeSpecification(searchTerm)) {
const { startTime, endTime } = paramToTime(searchTerm);
searchTimes.push([searchTerm, startTime, endTime]);
}
});
return {
searchTerms: allSearchTerms.filter(searchTerm => !isValidTimeSpecification(searchTerm)),
searchTimes,
};
// }
// return convertSearchParamsToPictureFilters(searchParams);
}, [/*isAllSearchActive,*/ searchParams]);
if (import.meta.env.MODE === 'development')
getSearchResultPictureIds(queryParams, '').then(res => console.log('search results:', res));
const { linkToCollection, bulkEdit } = useBulkOperations();

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { MeiliSearch } from 'meilisearch';

const dateToTimeStamp = (date: string) => {
return Date.parse(date) / 1000;
};

const getSearchResultPictureIds = async (
{ searchTerms, searchTimes }: { searchTerms: string[]; searchTimes: string[][] },
filter: string
) => {
const client = new MeiliSearch({
host: 'localhost:7700',
apiKey: '',
});
const index = client.index('picture');

const TIME_RANGE_START = 'time_range_tag_start';
const TIME_RANGE_END = 'time_range_tag_end';
// when building a filter for meilisearch the filtered attribute always
// has to come first i.e. time_range_start >= 0 works but 0 <= time_range_start does not work
if (searchTimes.length !== 0) {
const timeFilters = searchTimes.map(
searchTime =>
`(${TIME_RANGE_START} >= ${dateToTimeStamp(
searchTime[1]
)} AND ${TIME_RANGE_END} <= ${dateToTimeStamp(searchTime[2])})`
);

const timeFilter = timeFilters.join(' OR ');
filter = filter === '' ? timeFilter : filter.concat(' AND ', timeFilter);
}

const RESULT_LIMIT = 1000;
// this makes it so only documents that match all of the query terms are returned
const MATCHING_STRATEGY = 'all';

const settings = {
limit: RESULT_LIMIT,
showMatchesPosition: true,
matchingStrategy: MATCHING_STRATEGY,
filter: filter,
};
const query = searchTerms.length !== 0 ? searchTerms.join(' ') : '';
const searchResult = await index.search(query, settings);
return searchResult.hits;
};

export default getSearchResultPictureIds;
2 changes: 1 addition & 1 deletion projects/bp-gallery/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import react from '@vitejs/plugin-react-swc';
import { defineConfig } from 'vite';
import type { Plugin, PluginBuild } from 'esbuild';
import path from 'path';
import { defineConfig } from 'vite';
import eslint from 'vite-plugin-eslint';

const splitPackages = ['@mui/icons-material', '@mui/material'];
Expand Down
21 changes: 21 additions & 0 deletions projects/bp-gallery/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3422,6 +3422,13 @@ cross-fetch@3.1.5, cross-fetch@^3.1.5:
dependencies:
node-fetch "2.6.7"

cross-fetch@^3.1.6:
version "3.1.6"
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.6.tgz#bae05aa31a4da760969756318feeee6e70f15d6c"
integrity sha512-riRvo06crlE8HiqOwIpQhxwdOk4fOeR7FVM/wXoxchFEqMNUjvbs3bfo4OTgMEMHzppd4DxFBDbyySj8Cv781g==
dependencies:
node-fetch "^2.6.11"

cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
Expand Down Expand Up @@ -5978,6 +5985,13 @@ map-stream@~0.1.0:
resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194"
integrity sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==

meilisearch@^0.33.0:
version "0.33.0"
resolved "https://registry.yarnpkg.com/meilisearch/-/meilisearch-0.33.0.tgz#25982b193cdd22e9ec534a022dbde89c42951dc4"
integrity sha512-bYPb9WyITnJfzf92e7QFK8Rc50DmshFWxypXCs3ILlpNh8pT15A7KSu9Xgnnk/K3G/4vb3wkxxtFS4sxNkWB8w==
dependencies:
cross-fetch "^3.1.6"

meow@^9.0.0:
version "9.0.0"
resolved "https://registry.yarnpkg.com/meow/-/meow-9.0.0.tgz#cd9510bc5cac9dee7d03c73ee1f9ad959f4ea364"
Expand Down Expand Up @@ -6251,6 +6265,13 @@ node-fetch@2.6.7, node-fetch@^2.6.1, node-fetch@^2.6.7:
dependencies:
whatwg-url "^5.0.0"

node-fetch@^2.6.11:
version "2.6.11"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.11.tgz#cde7fc71deef3131ef80a738919f999e6edfff25"
integrity sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==
dependencies:
whatwg-url "^5.0.0"

node-gyp@^8.4.1:
version "8.4.1"
resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-8.4.1.tgz#3d49308fc31f768180957d6b5746845fbd429937"
Expand Down
119 changes: 119 additions & 0 deletions projects/bp-strapi/config/plugins.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
/* eslint-disable no-unused-vars */

const dateToTimeStamp = (date) => {
return Date.parse(date) / 1000;
};

module.exports = ({ env }) => ({
// disable i18n (all content is explicitly german as it's a german photo archive)
i18n: false,
Expand Down Expand Up @@ -58,6 +63,120 @@ module.exports = ({ env }) => ({
},
},
},
meilisearch:
env("MEILISEARCH_ENABLED", "false") === "true"
? {
config: {
host: env("MEILISEARCH_HOST"),
apiKey: env("MEILISEARCH_API_KEY"),
picture: {
transformEntry({ entry }) {
const transformedEntry = {
id: entry.id,
likes: entry.likes,
descriptions: entry.descriptions.map(
(description) => description.text
),
comments: entry.comments.map((comment) => comment.text),
keyword_tags: entry.keyword_tags
.map((tag) => tag.name)
.concat(entry.verified_keyword_tags.map((tag) => tag.name)),
person_tags: entry.person_tags
.map((tag) => tag.name)
.concat(entry.verified_person_tags.map((tag) => tag.name)),
location_tags: entry.location_tags
.map((tag) => tag.name)
.concat(
entry.verified_location_tags.map((tag) => tag.name)
),
face_tags: entry.face_tags.map((tag) => tag.name),
collections: entry.collections.map((tag) => tag.name),
archive_tag: entry.archive_tag,
time_range_tag_start: entry?.time_range_tag
? dateToTimeStamp(entry.time_range_tag.start)
: entry.verified_time_range_tag
? dateToTimeStamp(entry.verified_time_range_tag.start)
: null,
time_range_tag_end: entry?.time_range_tag
? dateToTimeStamp(entry.time_range_tag.end)
: entry.verified_time_range_tag
? dateToTimeStamp(entry.verified_time_range_tag.end)
: null,
};

return transformedEntry;
},
settings: {
displayedAttributes: ["id"],
// the order of the attributes in searchableAttributes determines the priorization
// of search results i.e. a match in the first searchable attribute will always outrank a match in any other searchable attribute
searchableAttributes: [
"descriptions",
"keyword_tags",
"location_tags",
"time_range_tag_start",
"time_range_tag_end",
"face_tags",
"person_tags",
"collections",
"archive_tag",
"comments",
],
filterableAttributes: [
"keyword_tags",
"location_tags",
"time_range_tag_start",
"time_range_tag_end",
"face_tags",
"person_tags",
"descriptions",
"comments",
"collections",
"archive_tag",
"is_text",
],
sortableAttributes: [
"time_range_tag_start",
"time_range_tag_end",
"likes",
],
rankingRules: [
"words",
"typo",
"proximity",
"attribute",
"sort",
"exactness",
],
// words that are ignored during searches, useful for common words
// that do not carry a meaning on their own like articles, pronomina etc.
// we do not use this setting, since our data on user searchers suggests, that
// users only search for proper names, people, locations and nouns in general
stopWords: [],
synonyms: {},
// returned documents will always be unigue in this attribute
distinctAttribute: null,
typoTolerance: {
enabled: true,
minWordSizeForTypos: { oneTypo: 3, twoTypos: 4 },
disableOnWords: [],
disableOnAttributes: [],
},
// faceting is currently not in use
faceting: {
maxValuesPerFacet: 100,
},
// maxtotalHits determines the maximal possible amount
// of search results and overrides any other settings
// like the result_limit of the search settings in this regard
pagination: {
maxTotalHits: 1000,
},
},
},
},
}
: null,
upload:
env("AWS_ENABLED", "false") === "true"
? {
Expand Down
2 changes: 2 additions & 0 deletions projects/bp-strapi/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
"pg": "8.6.0",
"pm2": "^5.2.0",
"sendmail": "^1.6.1",
"sharp": "^0.32.1",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked this up and it seems to be related to image optimization. Do we do some sort of image search or why do we need this package?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i merged staging into my local branch and and suddenly got errors because the sharp package was missing, so installed it. I don't know where this dependency comes from

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strange, for me it works without the package

"strapi-plugin-meilisearch": "^0.9.2",
"strapi-provider-upload-aws-s3-advanced": "^5.0.1",
"xlsx": "^0.18.5"
},
Expand Down
Loading