Skip to content

Commit

Permalink
Merge pull request #260 from colonial-heritage/feat-facets
Browse files Browse the repository at this point in the history
feat: facets
  • Loading branch information
sdevalk authored Oct 3, 2023
2 parents f7f0d12 + 5035992 commit 02fac3b
Show file tree
Hide file tree
Showing 3 changed files with 292 additions and 2 deletions.
3 changes: 3 additions & 0 deletions apps/researcher/src/lib/api/objects/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@ export type SearchResult = {
types: SearchResultFilter[];
subjects: SearchResultFilter[];
locations: SearchResultFilter[];
materials: SearchResultFilter[];
creators: SearchResultFilter[];
publishers: SearchResultFilter[];
};
};
256 changes: 256 additions & 0 deletions apps/researcher/src/lib/api/objects/searcher.integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,262 @@ describe('search', () => {
name: 'Suriname',
},
],
materials: [
{
totalCount: 2,
id: 'Canvas',
name: 'Canvas',
},
{
totalCount: 1,
id: 'Ink',
name: 'Ink',
},
{
totalCount: 2,
id: 'Oilpaint',
name: 'Oilpaint',
},
{
totalCount: 2,
id: 'Paper',
name: 'Paper',
},
],
creators: [
{
totalCount: 1,
id: 'Adriaan Boer',
name: 'Adriaan Boer',
},
{
totalCount: 1,
id: 'Geeske van Châtellerault',
name: 'Geeske van Châtellerault',
},
{
totalCount: 1,
id: 'Vincent van Gogh',
name: 'Vincent van Gogh',
},
],
publishers: [
{
totalCount: 0,
id: 'Archive',
name: 'Archive',
},
{
totalCount: 1,
id: 'Library',
name: 'Library',
},
{
totalCount: 3,
id: 'Museum',
name: 'Museum',
},
{
totalCount: 1,
id: 'Onderzoeksinstelling',
name: 'Onderzoeksinstelling',
},
{
totalCount: 1,
id: 'Research Organisation',
name: 'Research Organisation',
},
],
},
});
});

it('finds heritage objects if "owners" filter matches', async () => {
const result = await heritageObjectSearcher.search({
filters: {
owners: ['Library'],
},
});

expect(result).toMatchObject({
totalCount: 1,
filters: {
owners: [
{totalCount: 1, id: 'Library', name: 'Library'},
{totalCount: 0, id: 'Museum', name: 'Museum'},
{
totalCount: 0,
id: 'Research Organisation',
name: 'Research Organisation',
},
],
},
});
});

it('finds heritage objects if "types" filter matches', async () => {
const result = await heritageObjectSearcher.search({
filters: {
types: ['Painting'],
},
});

expect(result).toMatchObject({
totalCount: 1,
filters: {
types: [
{totalCount: 0, id: 'Canvas Painting', name: 'Canvas Painting'},
{totalCount: 0, id: 'Drawing', name: 'Drawing'},
{totalCount: 1, id: 'Painting', name: 'Painting'},
{totalCount: 0, id: 'Photo', name: 'Photo'},
],
},
});
});

it('finds heritage objects if "subjects" filter matches', async () => {
const result = await heritageObjectSearcher.search({
filters: {
subjects: ['Castle'],
},
});

expect(result).toMatchObject({
totalCount: 1,
filters: {
subjects: [
{totalCount: 1, id: 'Castle', name: 'Castle'},
{totalCount: 0, id: 'Celebrations', name: 'Celebrations'},
{totalCount: 1, id: 'Cottage', name: 'Cottage'},
{totalCount: 0, id: 'Palace', name: 'Palace'},
],
},
});
});

it('finds heritage objects if "locations" filter matches', async () => {
const result = await heritageObjectSearcher.search({
filters: {
locations: ['Malaysia'],
},
});

expect(result).toMatchObject({
totalCount: 1,
filters: {
locations: [
{totalCount: 0, id: 'Indonesia', name: 'Indonesia'},
{totalCount: 1, id: 'Malaysia', name: 'Malaysia'},
{totalCount: 0, id: 'Suriname', name: 'Suriname'},
],
},
});
});

it('finds heritage objects if "materials" filter matches', async () => {
const result = await heritageObjectSearcher.search({
filters: {
materials: ['Canvas'],
},
});

expect(result).toMatchObject({
totalCount: 2,
filters: {
materials: [
{
totalCount: 2,
id: 'Canvas',
name: 'Canvas',
},
{
totalCount: 0,
id: 'Ink',
name: 'Ink',
},
{
totalCount: 2,
id: 'Oilpaint',
name: 'Oilpaint',
},
{
totalCount: 0,
id: 'Paper',
name: 'Paper',
},
],
},
});
});

it('finds heritage objects if "creators" filter matches', async () => {
const result = await heritageObjectSearcher.search({
filters: {
creators: ['Adriaan Boer'],
},
});

expect(result).toMatchObject({
totalCount: 1,
filters: {
creators: [
{
totalCount: 1,
id: 'Adriaan Boer',
name: 'Adriaan Boer',
},
{
totalCount: 0,
id: 'Geeske van Châtellerault',
name: 'Geeske van Châtellerault',
},
{
totalCount: 0,
id: 'Vincent van Gogh',
name: 'Vincent van Gogh',
},
],
},
});
});

it('finds heritage objects if "publishers" filter matches', async () => {
const result = await heritageObjectSearcher.search({
filters: {
publishers: ['Library'],
},
});

expect(result).toMatchObject({
totalCount: 1,
filters: {
publishers: [
{
totalCount: 0,
id: 'Archive',
name: 'Archive',
},
{
totalCount: 1,
id: 'Library',
name: 'Library',
},
{
totalCount: 0,
id: 'Museum',
name: 'Museum',
},
{
totalCount: 0,
id: 'Onderzoeksinstelling',
name: 'Onderzoeksinstelling',
},
{
totalCount: 0,
id: 'Research Organisation',
name: 'Research Organisation',
},
],
},
});
});
Expand Down
35 changes: 33 additions & 2 deletions apps/researcher/src/lib/api/objects/searcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ enum RawKeys {
Image = 'https://colonialcollections nl/schema#image',
Owner = 'https://colonialcollections nl/schema#owner',
Publisher = 'https://colonialcollections nl/schema#publisher',
DateCreated = 'https://colonialcollections nl/schema#dateCreatedStart', // Earliest date of creation
CountryCreated = 'https://colonialcollections nl/schema#countryCreated',
IsPartOf = 'https://colonialcollections nl/schema#isPartOf',
}
Expand All @@ -61,6 +60,9 @@ const searchOptionsSchema = z.object({
types: z.array(z.string()).optional().default([]),
subjects: z.array(z.string()).optional().default([]),
locations: z.array(z.string()).optional().default([]),
materials: z.array(z.string()).optional().default([]),
creators: z.array(z.string()).optional().default([]),
publishers: z.array(z.string()).optional().default([]),
})
.optional(),
});
Expand All @@ -82,7 +84,6 @@ const rawHeritageObjectSchema = z
.setKey(RawKeys.Image, z.array(z.string()).optional())
.setKey(RawKeys.Owner, z.array(z.string()).optional())
.setKey(RawKeys.Publisher, z.array(z.string()).optional())
.setKey(RawKeys.DateCreated, z.array(z.string()).optional())
.setKey(RawKeys.IsPartOf, z.array(z.string()).min(1));

type RawHeritageObject = z.infer<typeof rawHeritageObjectSchema>;
Expand Down Expand Up @@ -119,11 +120,17 @@ const rawSearchResponseWithAggregationsSchema = rawSearchResponseSchema.merge(
types: rawAggregationSchema,
subjects: rawAggregationSchema,
locations: rawAggregationSchema,
materials: rawAggregationSchema,
creators: rawAggregationSchema,
publishers: rawAggregationSchema,
}),
owners: rawAggregationSchema,
types: rawAggregationSchema,
subjects: rawAggregationSchema,
locations: rawAggregationSchema,
materials: rawAggregationSchema,
creators: rawAggregationSchema,
publishers: rawAggregationSchema,
}),
})
);
Expand Down Expand Up @@ -258,6 +265,9 @@ export class HeritageObjectSearcher {
types: buildAggregation(RawKeys.AdditionalType),
subjects: buildAggregation(RawKeys.About),
locations: buildAggregation(RawKeys.CountryCreated),
materials: buildAggregation(RawKeys.Material),
creators: buildAggregation(RawKeys.Creator),
publishers: buildAggregation(RawKeys.Publisher),
};

const sortByRawKey = sortByToRawKeys.get(options.sortBy!)!;
Expand Down Expand Up @@ -310,6 +320,9 @@ export class HeritageObjectSearcher {
[RawKeys.AdditionalType, options.filters?.types],
[RawKeys.About, options.filters?.subjects],
[RawKeys.CountryCreated, options.filters?.locations],
[RawKeys.Material, options.filters?.materials],
[RawKeys.Creator, options.filters?.creators],
[RawKeys.Publisher, options.filters?.publishers],
]);

for (const [rawHeritageObjectKey, filters] of queryFilters) {
Expand Down Expand Up @@ -356,6 +369,21 @@ export class HeritageObjectSearcher {
aggregations.locations.buckets
);

const materialFilters = buildFilters(
aggregations.all.materials.buckets,
aggregations.materials.buckets
);

const creatorFilters = buildFilters(
aggregations.all.creators.buckets,
aggregations.creators.buckets
);

const publisherFilters = buildFilters(
aggregations.all.publishers.buckets,
aggregations.publishers.buckets
);

const searchResult: SearchResult = {
totalCount: hits.total.value,
offset: options.offset!,
Expand All @@ -368,6 +396,9 @@ export class HeritageObjectSearcher {
types: typeFilters,
subjects: subjectFilters,
locations: locationFilters,
materials: materialFilters,
creators: creatorFilters,
publishers: publisherFilters,
},
};

Expand Down

2 comments on commit 02fac3b

@vercel
Copy link

@vercel vercel bot commented on 02fac3b Oct 3, 2023

Choose a reason for hiding this comment

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

@vercel
Copy link

@vercel vercel bot commented on 02fac3b Oct 3, 2023

Choose a reason for hiding this comment

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

Please sign in to comment.