Skip to content

Commit

Permalink
fix: fix where scope on search (#1245)
Browse files Browse the repository at this point in the history
  • Loading branch information
pyphilia authored Jul 26, 2024
1 parent fe76981 commit 6d6c2b9
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 67 deletions.
50 changes: 30 additions & 20 deletions src/services/item/plugins/geolocation/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// @ts-expect-error
import { iso1A2Code } from '@rapideditor/country-coder';
import fetch from 'node-fetch';
import { EntityManager, Repository } from 'typeorm';
import { Brackets, EntityManager, Repository } from 'typeorm';

import { DEFAULT_LANG } from '@graasp/translations';

Expand Down Expand Up @@ -115,28 +115,38 @@ export class ItemGeolocationRepository {
query.andWhere('item.path <@ :path', { path: parentItem.path });
}

if (keywords?.filter((s) => s.length)?.length) {
const keywordsString = keywords.join(' ');
const allKeywords = keywords?.filter((s) => s && s.length);
if (allKeywords?.length) {
const keywordsString = allKeywords.join(' ');
const memberLang = actor?.lang;
query.andWhere((q) => {
// search in english by default
q.where("item.search_document @@ plainto_tsquery('english', :keywords)", {
keywords: keywordsString,
});

// no dictionary
q.orWhere("item.search_document @@ plainto_tsquery('simple', :keywords)", {
keywords: keywordsString,
});

// search by member lang
if (memberLang && memberLang != 'en' && ALLOWED_SEARCH_LANGS[memberLang]) {
q.orWhere('item.search_document @@ plainto_tsquery(:lang, :keywords)', {
query.andWhere(
new Brackets((q) => {
// search in english by default
q.where("item.search_document @@ plainto_tsquery('english', :keywords)", {
keywords: keywordsString,
lang: ALLOWED_SEARCH_LANGS[memberLang],
});
}
});

// no dictionary
q.orWhere("item.search_document @@ plainto_tsquery('simple', :keywords)", {
keywords: keywordsString,
});

// raw words search
allKeywords.forEach((k, idx) => {
q.orWhere(`item.name ILIKE :k_${idx}`, {
[`k_${idx}`]: `%${k}%`,
});
});

// search by member lang
if (memberLang && memberLang != 'en' && ALLOWED_SEARCH_LANGS[memberLang]) {
q.orWhere('item.search_document @@ plainto_tsquery(:lang, :keywords)', {
keywords: keywordsString,
lang: ALLOWED_SEARCH_LANGS[memberLang],
});
}
}),
);
}

return query.getMany();
Expand Down
48 changes: 25 additions & 23 deletions src/services/item/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,33 +203,35 @@ export class ItemRepository {
const allKeywords = params?.keywords?.filter((s) => s && s.length);
if (allKeywords?.length) {
const keywordsString = allKeywords.join(' ');
query.andWhere((q) => {
// search in english by default
q.where("item.search_document @@ plainto_tsquery('english', :keywords)", {
keywords: keywordsString,
});

// no dictionary
q.orWhere("item.search_document @@ plainto_tsquery('simple', :keywords)", {
keywords: keywordsString,
});

// raw words search
allKeywords.forEach((k, idx) => {
q.orWhere(`item.name ILIKE :k_${idx}`, {
[`k_${idx}`]: `%${k}%`,
query.andWhere(
new Brackets((q) => {
// search in english by default
q.where("item.search_document @@ plainto_tsquery('english', :keywords)", {
keywords: keywordsString,
});
});

// search by member lang
const memberLang = actor?.lang;
if (memberLang && memberLang != 'en' && ALLOWED_SEARCH_LANGS[memberLang]) {
q.orWhere('item.search_document @@ plainto_tsquery(:lang, :keywords)', {
// no dictionary
q.orWhere("item.search_document @@ plainto_tsquery('simple', :keywords)", {
keywords: keywordsString,
lang: ALLOWED_SEARCH_LANGS[memberLang],
});
}
});

// raw words search
allKeywords.forEach((k, idx) => {
q.orWhere(`item.name ILIKE :k_${idx}`, {
[`k_${idx}`]: `%${k}%`,
});
});

// search by member lang
const memberLang = actor?.lang;
if (memberLang && memberLang != 'en' && ALLOWED_SEARCH_LANGS[memberLang]) {
q.orWhere('item.search_document @@ plainto_tsquery(:lang, :keywords)', {
keywords: keywordsString,
lang: ALLOWED_SEARCH_LANGS[memberLang],
});
}
}),
);
}

if (params?.ordered) {
Expand Down
50 changes: 50 additions & 0 deletions src/services/item/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1271,6 +1271,12 @@ describe('Item routes tests', () => {
member: actor,
item: { name: 'cat' },
});
// noise
const member = await saveMember();
await testUtils.saveItemAndMembership({
member,
item: { name: 'dog' },
});

const items = [item1, item2];

Expand Down Expand Up @@ -1644,6 +1650,50 @@ describe('Item routes tests', () => {
});
expect(response.statusCode).toBe(StatusCodes.OK);
});

it('Returns successfully children with search', async () => {
const member = await saveMember();
const { item: parent } = await testUtils.saveItemAndMembership({
member: actor,
creator: member,
permission: PermissionLevel.Read,
});
const { packedItem: item1 } = await testUtils.saveItemAndMembership({
member: actor,
item: { name: 'dog' },
parentItem: parent,
});
const { packedItem: item2 } = await testUtils.saveItemAndMembership({
member: actor,
item: { name: 'dog' },
parentItem: parent,
});
await testUtils.saveItemAndMembership({
member: actor,
item: { name: 'cat' },
parentItem: parent,
});
// noise
await testUtils.saveItemAndMembership({
member,
item: { name: 'dog' },
});

const items = [item1, item2];

const response = await app.inject({
method: HttpMethod.Get,
url: `/items/${parent.id}/children`,
query: { keywords: ['dogs'] },
});

expect(response.statusCode).toBe(StatusCodes.OK);

const data = response.json();
expect(data).toHaveLength(items.length);
expectManyPackedItems(data, items);
});

it('Bad Request for invalid id', async () => {
const response = await app.inject({
method: HttpMethod.Get,
Expand Down
50 changes: 26 additions & 24 deletions src/services/itemMembership/repository.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { In, Not } from 'typeorm';
import { Brackets, In, Not } from 'typeorm';

import {
Paginated,
Expand Down Expand Up @@ -165,33 +165,35 @@ export const ItemMembershipRepository = AppDataSource.getRepository(ItemMembersh
const allKeywords = keywords?.filter((s) => s && s.length);
if (allKeywords?.length) {
const keywordsString = allKeywords.join(' ');
query.andWhere((q) => {
// search in english by default
q.where("item.search_document @@ plainto_tsquery('english', :keywords)", {
keywords: keywordsString,
});

// no dictionary
q.orWhere("item.search_document @@ plainto_tsquery('simple', :keywords)", {
keywords: keywordsString,
});

// raw words search
allKeywords.forEach((k, idx) => {
q.orWhere(`item.name ILIKE :k_${idx}`, {
[`k_${idx}`]: `%${k}%`,
query.andWhere(
new Brackets((q) => {
// search in english by default
q.where("item.search_document @@ plainto_tsquery('english', :keywords)", {
keywords: keywordsString,
});
});

// search by member lang
const memberLang = actor.lang;
if (memberLang != 'en' && ALLOWED_SEARCH_LANGS[memberLang]) {
q.orWhere('item.search_document @@ plainto_tsquery(:lang, :keywords)', {
// no dictionary
q.orWhere("item.search_document @@ plainto_tsquery('simple', :keywords)", {
keywords: keywordsString,
lang: ALLOWED_SEARCH_LANGS[memberLang],
});
}
});

// raw words search
allKeywords.forEach((k, idx) => {
q.orWhere(`item.name ILIKE :k_${idx}`, {
[`k_${idx}`]: `%${k}%`,
});
});

// search by member lang
const memberLang = actor.lang;
if (memberLang != 'en' && ALLOWED_SEARCH_LANGS[memberLang]) {
q.orWhere('item.search_document @@ plainto_tsquery(:lang, :keywords)', {
keywords: keywordsString,
lang: ALLOWED_SEARCH_LANGS[memberLang],
});
}
}),
);
}

if (creatorId) {
Expand Down

0 comments on commit 6d6c2b9

Please sign in to comment.