Skip to content

Commit 6b21eea

Browse files
[DSC-1988] Limit the number of items requested by search manager
1 parent 66bc5ac commit 6b21eea

10 files changed

Lines changed: 53 additions & 10 deletions

File tree

src/app/core/browse/search-manager.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ export class SearchManager {
111111
})
112112
.filter((item) => hasValue(item));
113113

114-
const uuidList = this.extractUUID(items, environment.followAuthorityMetadata);
114+
const uuidList = this.extractUUID(items, environment.followAuthorityMetadata, 100);
115+
115116
return uuidList.length > 0 ? this.itemService.findAllById(uuidList).pipe(
116117
getFirstCompletedRemoteData(),
117118
map(data => {
@@ -124,27 +125,31 @@ export class SearchManager {
124125
) : of(null);
125126
}
126127

127-
protected extractUUID(items: Item[], metadataToFollow: FollowAuthorityMetadata[]): string[] {
128+
protected extractUUID(items: Item[], metadataToFollow: FollowAuthorityMetadata[], numberOfElementsToReturn?: number): string[] {
128129
const uuidMap = {};
129130

130131
items.forEach((item) => {
131132
metadataToFollow.forEach((followMetadata: FollowAuthorityMetadata) => {
132133
if (item.entityType === followMetadata.type) {
133134
if (isArray(followMetadata.metadata)) {
134-
followMetadata.metadata.forEach((metadata) => {
135-
Metadata.all(item.metadata, metadata)
135+
followMetadata.metadata.forEach((metadata) => {
136+
Metadata.all(item.metadata, metadata, null, environment.followAuthorityMetadataValuesLimit)
136137
.filter((metadataValue: MetadataValue) => Metadata.hasValidItemAuthority(metadataValue.authority))
137138
.forEach((metadataValue: MetadataValue) => uuidMap[metadataValue.authority] = metadataValue);
138139
});
139140
} else {
140-
Metadata.all(item.metadata, followMetadata.metadata)
141+
Metadata.all(item.metadata, followMetadata.metadata, null, environment.followAuthorityMetadataValuesLimit)
141142
.filter((metadataValue: MetadataValue) => Metadata.hasValidItemAuthority(metadataValue.authority))
142143
.forEach((metadataValue: MetadataValue) => uuidMap[metadataValue.authority] = metadataValue);
143144
}
144145
}
145146
});
146147
});
147148

149+
if (hasValue(numberOfElementsToReturn) && numberOfElementsToReturn > 0) {
150+
return Object.keys(uuidMap).slice(0, numberOfElementsToReturn);
151+
}
152+
148153
return Object.keys(uuidMap);
149154
}
150155
}

src/app/core/browse/search.manager.spec.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,11 @@ describe('SearchManager', () => {
182182
const uuidList = (service as any).extractUUID([firstPublication, firstPublication], [{type: 'Publication', metadata: ['dc.contributor.author']}]);
183183
expect(uuidList).toEqual([validAuthority]);
184184
});
185+
186+
it('should limit the number of extracted uuids', () => {
187+
const uuidList = (service as any).extractUUID([firstPublication, secondPublication, invalidAuthorityPublication], [{type: 'Publication', metadata: ['dc.contributor.author']}], 2);
188+
expect(uuidList.length).toBe(2);
189+
});
185190
});
186191

187192
});

src/app/core/shared/dspace-object.model.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,18 @@ export class DSpaceObject extends ListableObject implements CacheableObject {
115115
return Metadata.all(this.metadata, keyOrKeys, valueFilter);
116116
}
117117

118+
/**
119+
* Gets all matching metadata in this DSpaceObject, up to a limit.
120+
*
121+
* @param {string|string[]} keyOrKeys The metadata key(s) in scope. Wildcards are supported; see [[Metadata]].
122+
* @param {number} limit The maximum number of results to return.
123+
* @param {MetadataValueFilter} valueFilter The value filter to use. If unspecified, no filtering will be done.
124+
* @returns {MetadataValue[]} the matching values or an empty array.
125+
*/
126+
limitedMetadata(keyOrKeys: string | string[], limit: number, valueFilter?: MetadataValueFilter): MetadataValue[] {
127+
return Metadata.all(this.metadata, keyOrKeys, valueFilter, limit);
128+
}
129+
118130
/**
119131
* Like [[allMetadata]], but only returns string values.
120132
*

src/app/core/shared/metadata.utils.spec.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,20 @@ const multiViewModelList = [
4444
{ key: 'foo', ...bar, order: 0 }
4545
];
4646

47-
const testMethod = (fn, resultKind, mapOrMaps, keyOrKeys, expected, filter?) => {
47+
const testMethod = (fn, resultKind, mapOrMaps, keyOrKeys, expected, filter?, limit?: number) => {
4848
const keys = keyOrKeys instanceof Array ? keyOrKeys : [keyOrKeys];
4949
describe('and key' + (keys.length === 1 ? (' ' + keys[0]) : ('s ' + JSON.stringify(keys)))
5050
+ ' with ' + (isUndefined(filter) ? 'no filter' : 'filter ' + JSON.stringify(filter)), () => {
51-
const result = fn(mapOrMaps, keys, filter);
51+
const result = fn(mapOrMaps, keys, filter, limit);
5252
let shouldReturn;
5353
if (resultKind === 'boolean') {
5454
shouldReturn = expected;
5555
} else if (isUndefined(expected)) {
5656
shouldReturn = 'undefined';
5757
} else if (expected instanceof Array) {
5858
shouldReturn = 'an array with ' + expected.length + ' ' + (expected.length > 1 ? 'ordered ' : '')
59-
+ resultKind + (expected.length !== 1 ? 's' : '');
59+
+ resultKind + (expected.length !== 1 ? 's' : '')
60+
+ (isUndefined(limit) ? '' : ' (limited to ' + limit + ')');
6061
} else {
6162
shouldReturn = 'a ' + resultKind;
6263
}
@@ -297,4 +298,12 @@ describe('Metadata', () => {
297298

298299
});
299300

301+
describe('all method with limit', () => {
302+
const testAllWithLimit = (mapOrMaps, keyOrKeys, expected, limit) =>
303+
testMethod(Metadata.all, 'value', mapOrMaps, keyOrKeys, expected, undefined, limit);
304+
305+
describe('with multiMap and limit', () => {
306+
testAllWithLimit(multiMap, 'dc.title', [dcTitle1], 1);
307+
});
308+
});
300309
});

src/app/core/shared/metadata.utils.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,11 @@ export class Metadata {
3737
* checked in order, and only values from the first with at least one match will be returned.
3838
* @param {string|string[]} keyOrKeys The metadata key(s) in scope. Wildcards are supported; see above.
3939
* @param {MetadataValueFilter} filter The value filter to use. If unspecified, no filtering will be done.
40+
* @param {number} limit The maximum number of values to return. If unspecified, all matching values will be returned.
4041
* @returns {MetadataValue[]} the matching values or an empty array.
4142
*/
4243
public static all(mapOrMaps: MetadataMapInterface | MetadataMapInterface[], keyOrKeys: string | string[],
43-
filter?: MetadataValueFilter): MetadataValue[] {
44+
filter?: MetadataValueFilter, limit?: number): MetadataValue[] {
4445
const mdMaps: MetadataMapInterface[] = mapOrMaps instanceof Array ? mapOrMaps : [mapOrMaps];
4546
const matches: MetadataValue[] = [];
4647
for (const mdMap of mdMaps) {
@@ -50,6 +51,9 @@ export class Metadata {
5051
for (const candidate of candidates) {
5152
if (Metadata.valueMatches(candidate as MetadataValue, filter)) {
5253
matches.push(candidate as MetadataValue);
54+
if (hasValue(limit) && matches.length >= limit) {
55+
return matches;
56+
}
5357
}
5458
}
5559
}

src/app/shared/object-list/my-dspace-result-list-element/item-list-preview/item-list-preview.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ <h3 [innerHTML]="dsoTitle" [ngClass]="{'lead': true,'text-muted': !item.firstMet
1818
<span class="item-list-date" [innerHTML]="item.firstMetadataValue('dc.date.issued') || ('mydspace.results.no-date' | translate)"></span>)
1919
<span *ngIf="item.hasMetadata(authorMetadata);" class="item-list-authors">
2020
<span *ngIf="item.allMetadataValues(authorMetadata).length === 0">{{'mydspace.results.no-authors' | translate}}</span>
21-
<span *ngFor="let author of item.allMetadata(authorMetadata); let i=index; let last=last;">
21+
<span *ngFor="let author of item.limitedMetadata(authorMetadata, authorMetadataLimit); let i=index; let last=last;">
2222
<ds-metadata-link-view *ngIf="!!item && !!author" [item]="item" [metadataName]="authorMetadata"
2323
[metadata]="author"></ds-metadata-link-view><span
2424
*ngIf="!last">; </span>

src/app/shared/object-list/my-dspace-result-list-element/item-list-preview/item-list-preview.component.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ export class ItemListPreviewComponent implements OnInit {
7777

7878
authorMetadata = environment.searchResult.authorMetadata;
7979

80+
authorMetadataLimit = environment.followAuthorityMetadataValuesLimit;
81+
8082
constructor(
8183
@Inject(APP_CONFIG) protected appConfig: AppConfig,
8284
public dsoNameService: DSONameService,

src/config/app-config.interface.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ interface AppConfig extends Config {
7070
suggestion: SuggestionConfig[];
7171
addToAnyPlugin: AddToAnyPluginConfig;
7272
followAuthorityMetadata: FollowAuthorityMetadata[];
73+
followAuthorityMetadataValuesLimit: number;
7374
metricVisualizationConfig: MetricVisualizationConfig[];
7475
attachmentRendering: AttachmentRenderingConfig;
7576
advancedAttachmentRendering: AdvancedAttachmentRenderingConfig;

src/config/default-app-config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,10 @@ export class DefaultAppConfig implements AppConfig {
404404
}
405405
];
406406

407+
// The maximum number of metadata values to process for each metadata key
408+
// when following authority metadata values.
409+
followAuthorityMetadataValuesLimit = 5;
410+
407411
// Collection Page Config
408412
collection: CollectionPageConfig = {
409413
edit: {

src/environments/environment.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ export const environment: BuildConfig = {
276276
metadata: ['dc.contributor.author']
277277
}
278278
],
279+
followAuthorityMetadataValuesLimit: 5,
279280
item: {
280281
edit: {
281282
undoTimeout: 10000 // 10 seconds

0 commit comments

Comments
 (0)