From daf93f128348e65801af4f4d8b2ba5bbda67f142 Mon Sep 17 00:00:00 2001 From: Olivia Guyot Date: Fri, 22 Sep 2023 12:22:49 +0200 Subject: [PATCH] feat(repository): add a getMatchesCount operation This gives the amount of results matching a filter. Very similar to search(), but might be used in the future to allow for better performance. Used in the records service --- .../src/lib/gn4/gn4-repository.spec.ts | 30 +++++++++++++++++-- .../repository/src/lib/gn4/gn4-repository.ts | 20 +++++++++++++ .../src/lib/records-repository.interface.ts | 2 ++ .../src/lib/records/records.service.spec.ts | 8 ++--- .../src/lib/records/records.service.ts | 8 ++--- 5 files changed, 55 insertions(+), 13 deletions(-) diff --git a/libs/api/repository/src/lib/gn4/gn4-repository.spec.ts b/libs/api/repository/src/lib/gn4/gn4-repository.spec.ts index 83801366bb..b363375441 100644 --- a/libs/api/repository/src/lib/gn4/gn4-repository.spec.ts +++ b/libs/api/repository/src/lib/gn4/gn4-repository.spec.ts @@ -38,7 +38,7 @@ class ElasticsearchServiceMock { class SearchApiServiceMock { search = jest.fn((bucket, payload) => { const body = JSON.parse(payload) - const count = body.size ?? 20 + const count = body.size || 1234 const result: EsSearchResponse = { hits: { hits: DATASET_RECORDS, @@ -122,6 +122,32 @@ describe('Gn4Repository', () => { expect(results.records).toStrictEqual(DATASET_RECORDS) }) }) + describe('getMatchesCount', () => { + let count: number + beforeEach(async () => { + count = await lastValueFrom( + repository.getMatchesCount({ + field1: '1234', + field2: { + abcd: true, + }, + }) + ) + }) + it('builds a payload with the specified uuid', () => { + expect(gn4Helper.getSearchRequestBody).toHaveBeenCalledWith( + {}, + 0, + 0, + undefined, + undefined, + { field1: '1234', field2: { abcd: true } } + ) + }) + it('returns the result count', () => { + expect(count).toStrictEqual(1234) + }) + }) describe('getByUniqueIdentifier', () => { let record: CatalogRecord beforeEach(async () => { @@ -204,7 +230,7 @@ describe('Gn4Repository', () => { expect(gn4Helper.buildAutocompletePayload).toHaveBeenCalledWith('blargz') }) it('returns the given results as records', () => { - expect(results.count).toBe(20) + expect(results.count).toBe(1234) expect(results.records).toStrictEqual(DATASET_RECORDS) }) }) diff --git a/libs/api/repository/src/lib/gn4/gn4-repository.ts b/libs/api/repository/src/lib/gn4/gn4-repository.ts index dd04a23046..74e8ad498f 100644 --- a/libs/api/repository/src/lib/gn4/gn4-repository.ts +++ b/libs/api/repository/src/lib/gn4/gn4-repository.ts @@ -10,6 +10,7 @@ import { import { Aggregations, AggregationsParams, + FieldFilters, } from '@geonetwork-ui/common/domain/search' import { map } from 'rxjs/operators' import { @@ -62,6 +63,25 @@ export class Gn4Repository implements RecordsRepositoryInterface { ) } + getMatchesCount(filters: FieldFilters): Observable { + return this.gn4SearchApi + .search( + 'records-count', + JSON.stringify({ + ...this.gn4SearchHelper.getSearchRequestBody( + {}, + 0, + 0, + undefined, + undefined, + filters + ), + track_total_hits: true, + }) + ) + .pipe(map((results: Gn4SearchResults) => results.hits.total?.value || 0)) + } + getByUniqueIdentifier( uniqueIdentifier: string ): Observable { diff --git a/libs/common/domain/src/lib/records-repository.interface.ts b/libs/common/domain/src/lib/records-repository.interface.ts index 63b9fa77cb..7e0efada38 100644 --- a/libs/common/domain/src/lib/records-repository.interface.ts +++ b/libs/common/domain/src/lib/records-repository.interface.ts @@ -2,6 +2,7 @@ import { Observable } from 'rxjs' import { Aggregations, AggregationsParams, + FieldFilters, SearchParams, SearchResults, } from './search' @@ -9,6 +10,7 @@ import { CatalogRecord } from './record/metadata.model' export abstract class RecordsRepositoryInterface { abstract search(params: SearchParams): Observable + abstract getMatchesCount(filters: FieldFilters): Observable abstract getByUniqueIdentifier( uniqueIdentifier: string ): Observable diff --git a/libs/feature/catalog/src/lib/records/records.service.spec.ts b/libs/feature/catalog/src/lib/records/records.service.spec.ts index cbdd8bc837..2b0b6f4d6b 100644 --- a/libs/feature/catalog/src/lib/records/records.service.spec.ts +++ b/libs/feature/catalog/src/lib/records/records.service.spec.ts @@ -1,11 +1,9 @@ -import { TestBed } from '@angular/core/testing' import { RecordsService } from './records.service' -import { SAMPLE_SEARCH_RESULTS } from '@geonetwork-ui/common/fixtures' import { of, throwError } from 'rxjs' import { RecordsRepositoryInterface } from '@geonetwork-ui/common/domain/records-repository.interface' class RecordsRepositoryMock { - search = jest.fn(() => of(SAMPLE_SEARCH_RESULTS)) + getMatchesCount = jest.fn(() => of(123)) } describe('RecordsService', () => { @@ -32,13 +30,13 @@ describe('RecordsService', () => { service.recordsCount$.subscribe() service.recordsCount$.subscribe() service.recordsCount$.subscribe() - expect(repository.search).toHaveBeenCalledTimes(1) + expect(repository.getMatchesCount).toHaveBeenCalledTimes(1) }) }) describe('when the request does not behave as expected', () => { beforeEach(() => { - repository.search = () => throwError(() => 'blargz') + repository.getMatchesCount = () => throwError(() => 'blargz') service = new RecordsService(repository) // create a new service to enable the changed repository behaviour }) it('emits 0', () => { diff --git a/libs/feature/catalog/src/lib/records/records.service.ts b/libs/feature/catalog/src/lib/records/records.service.ts index b5217b7a53..deb144f961 100644 --- a/libs/feature/catalog/src/lib/records/records.service.ts +++ b/libs/feature/catalog/src/lib/records/records.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core' import { Observable, of } from 'rxjs' -import { catchError, map, shareReplay } from 'rxjs/operators' +import { catchError, shareReplay } from 'rxjs/operators' import { RecordsRepositoryInterface } from '@geonetwork-ui/common/domain/records-repository.interface' @Injectable({ @@ -8,12 +8,8 @@ import { RecordsRepositoryInterface } from '@geonetwork-ui/common/domain/records }) export class RecordsService { recordsCount$: Observable = this.recordsRepository - .search({ - limit: 0, - offset: 0, - }) + .getMatchesCount({}) .pipe( - map((response) => response.count), shareReplay(1), catchError(() => of(0)) )