@natlibfi/melinda-record-matching 4.3.2-alpha.2 → 4.3.2-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -32,6 +32,7 @@ import {MarcRecord} from '@natlibfi/marc-record';
32
32
  import {MARCXML} from '@natlibfi/marc-record-serializers';
33
33
  import generateQueryList from './query-list';
34
34
  import {Error as MatchingError} from '@natlibfi/melinda-commons';
35
+ import chooseQueries from './choose-queries';
35
36
 
36
37
  export {searchTypes} from './query-list';
37
38
 
@@ -39,7 +40,7 @@ export class CandidateSearchError extends Error {}
39
40
 
40
41
  // serverMaxResults : maximum size of total search result available from the server, defaults to Aleph's 20000
41
42
 
42
- export default ({record, searchSpec, url, maxCandidates, maxRecordsPerRequest = 50, serverMaxResult = 20000}) => {
43
+ export default async ({record, searchSpec, url, maxCandidates, maxRecordsPerRequest = 50, serverMaxResult = 20000}) => {
43
44
  MarcRecord.setValidationOptions({subfieldValues: false});
44
45
 
45
46
  const debug = createDebugLogger('@natlibfi/melinda-record-matching:candidate-search');
@@ -59,6 +60,16 @@ export default ({record, searchSpec, url, maxCandidates, maxRecordsPerRequest =
59
60
  const queryList = queryListResult[0]?.queryList ? queryListResult[0].queryList : queryListResult;
60
61
  const queryListType = queryListResult[0]?.queryListType ? queryListResult[0].queryListType : undefined;
61
62
 
63
+ // if generateQueryList errored we should throw 422
64
+ if (queryList.length === 0) {
65
+ debug(`Empty list`);
66
+ throw new CandidateSearchError(`Generated query list contains no queries`);
67
+ }
68
+ if (queryListType && queryListType !== 'alternates') {
69
+ debug(`Unknown queryListType`);
70
+ throw new CandidateSearchError(`Generated query list has invalid type`);
71
+ }
72
+
62
73
  const client = createClient({
63
74
  url,
64
75
  maxRecordsPerRequest: adjustedMaxRecordsPerRequest,
@@ -67,33 +78,19 @@ export default ({record, searchSpec, url, maxCandidates, maxRecordsPerRequest =
67
78
  });
68
79
 
69
80
  debug(`Searching matches for ${inputRecordId}`);
70
- const chosenQueryList = choseQueries(queryList, queryListType);
81
+ const chosenQueryList = await filterQueryList({queryList, queryListType});
82
+ debug(`Chosen queries: ${JSON.stringify(chosenQueryList)}`);
71
83
 
72
- // eslint-disable-next-line require-await
73
- function choseQueries(queryList, queryListType) {
84
+ async function filterQueryList({queryList, queryListType, maxCandidates}) {
74
85
  debug(`Generated queryList (type: ${queryListType}) ${JSON.stringify(queryList)}`);
75
86
 
76
- // if generateQueryList errored we should throw 422
77
- if (queryList.length === 0) {
78
- throw new CandidateSearchError(`Generated query list contains no queries`);
79
- }
80
-
81
- if (queryListType && queryListType !== 'alternates') {
82
- throw new CandidateSearchError(`Generated query list has invalid type`);
83
- }
84
-
85
87
  if (queryListType === 'alternates' && queryList.length > 1) {
86
- //const [query] = queryList;
87
- //const totalResult = await retrieveTotal(query);
88
- // const totalsForQueries = queryList.map(query => retrieveTotal(query));
89
- //debug(`${JSON.stringify(totalResult)}`);
90
- return queryList;
91
- //return [];
88
+ const queryListResult = await chooseQueries({url, queryList, queryListType, maxCandidates});
89
+ debug(`queryListResult: ${JSON.stringify(queryListResult)}`);
90
+ return queryListResult.map(elem => elem.query);
92
91
  }
93
92
  return queryList;
94
93
  }
95
-
96
-
97
94
  // state.totalRecords : amount of candidate records available to the current query (undefined, if there was no queries left)
98
95
  // state.query : current query (undefined if there was no queries left)
99
96
  // state.searchCounter : sequence for current search for current query (undefined, if there we no queries left)
@@ -102,16 +99,11 @@ export default ({record, searchSpec, url, maxCandidates, maxRecordsPerRequest =
102
99
  // state.queryCounter : sequence for current query
103
100
  // state.maxedQueries : queries that resulted in more than serverMaxResults hits
104
101
 
102
+ return {search};
105
103
 
106
104
  // eslint-disable-next-line max-statements
107
- return async ({queryOffset = 0, resultSetOffset = 1, totalRecords = 0, searchCounter = 0, queryCandidateCounter = 0, queryCounter = 0, maxedQueries = []}) => {
105
+ async function search({queryOffset = 0, resultSetOffset = 1, totalRecords = 0, searchCounter = 0, queryCandidateCounter = 0, queryCounter = 0, maxedQueries = []}) {
108
106
 
109
- /*
110
- if (queryListType === 'alternates') {
111
- debug('Alternates - stop here');
112
- return {records: [], failures: [], queriesLeft: 0, queryCounter, maxedQueries};
113
- }
114
- */
115
107
  const query = chosenQueryList[queryOffset];
116
108
  debug(`Running query ${JSON.stringify(query)} (${queryOffset})`);
117
109
 
@@ -202,31 +194,7 @@ export default ({record, searchSpec, url, maxCandidates, maxRecordsPerRequest =
202
194
  });
203
195
  });
204
196
  }
205
- };
206
-
207
- /*
208
- async function retrieveTotal(query) {
209
- debug(`Searching for candidateTotals with query: ${query}`);
210
- totalClient.searchRetrieve(query)
211
- .on('error', err => {
212
- // eslint-disable-next-line functional/no-conditional-statements
213
- if (err instanceof SruSearchError) {
214
- debug(`SRU SruSearchError for query: ${query}: ${err}`);
215
- throw new CandidateSearchError(`SRU SruSearchError for getting total for query: ${query}: ${err}`);
216
- }
217
- debug(`SRU error for query: ${query}: ${err}`);
218
- throw new CandidateSearchError(`SRU error for getting total for query: ${query}: ${err}`);
219
- })
220
- .on('total', total => {
221
- debug(`Got total: ${total}`);
222
- return {query, total};
223
- })
224
- .on('end', end => {
225
- debug(`End ${JSON.stringify(end)}`);
226
- });
227
197
  }
228
- */
229
-
230
198
 
231
199
  function checkMaxedQuery(query, total, serverMaxResult) {
232
200
  if (total >= serverMaxResult) {
@@ -245,5 +213,4 @@ export default ({record, searchSpec, url, maxCandidates, maxRecordsPerRequest =
245
213
  debug(`Cannot yet find possible database record id from recordXML (length ${recordXML.length})`);
246
214
  return undefined;
247
215
  }
248
-
249
216
  };
@@ -46,6 +46,7 @@ describe('candidate-search', () => {
46
46
  }
47
47
  });
48
48
 
49
+ // eslint-disable-next-line max-statements
49
50
  async function callback({getFixture, factoryOptions, searchOptions, expectedFactoryError = false, expectedSearchError = false, enabled = true}) {
50
51
  const url = 'http://foo.bar';
51
52
 
@@ -54,16 +55,29 @@ describe('candidate-search', () => {
54
55
  }
55
56
 
56
57
  if (expectedFactoryError) {
58
+ debug(`We're expecting an error`);
57
59
  if (expectedFactoryError.isCandidateSearchError) {
58
- expect(() => createSearchInterface({...formatFactoryOptions(), url})).to.throw(CandidateSearchError, new RegExp(expectedFactoryError, 'u'));
60
+ try {
61
+ const result = createSearchInterface({...formatFactoryOptions(), url});
62
+ debug(result);
63
+ } catch (err) {
64
+ expect(err).to.equal(new CandidateSearchError(expectedFactoryError));
65
+ }
59
66
  return;
60
67
  }
61
68
 
62
- expect(() => createSearchInterface({...formatFactoryOptions(), url})).to.throw(new RegExp(expectedFactoryError, 'u'));
69
+ try {
70
+ const result = createSearchInterface({...formatFactoryOptions(), url});
71
+ debug(result);
72
+ } catch (err) {
73
+ expect(err).to.equal(new Error(expectedFactoryError));
74
+ }
63
75
  return;
64
76
  }
65
77
 
66
- const search = createSearchInterface({...formatFactoryOptions(), url});
78
+ const {search} = await createSearchInterface({...formatFactoryOptions(), url});
79
+ // eslint-disable-next-line no-console
80
+ console.log(search);
67
81
  await iterate({searchOptions, expectedSearchError});
68
82
 
69
83
  function formatFactoryOptions() {
@@ -212,8 +212,9 @@ export function bibTitleAuthorYearAlternates(record) {
212
212
  debug('bibTitleAuthorYearAlternates');
213
213
  // We use onlyTitleLength that is longer than our formatted length to
214
214
  // get an author or an publisher always
215
-
216
- return {queryList: bibTitleAuthorPublisher({record, onlyTitleLength: 100, addYear: true, alternates: true, alternateQueries: []}), queryListType: 'alternates'};
215
+ const origQueryList = bibTitleAuthorPublisher({record, onlyTitleLength: 100, addYear: true, alternates: true, alternateQueries: []});
216
+ debug(`${JSON.stringify(origQueryList)}`);
217
+ return {queryList: Array.from(origQueryList).reverse(), queryListType: 'alternates'};
217
218
  }
218
219
 
219
220
  export function bibTitleAuthorPublisher({record, onlyTitleLength, addYear = false, alternates = false, alternateQueries = []}) {
package/src/index.js CHANGED
@@ -49,9 +49,11 @@ export default ({detection: detectionOptions, search: searchOptions, maxMatches
49
49
 
50
50
  const detect = createDetectionInterface(detectionOptions, returnStrategy);
51
51
 
52
- return ({record, recordExternal = {recordSource: 'incomingRecord', label: 'ic'}}) => {
52
+ return prepareSearch;
53
53
 
54
- const search = createSearchInterface({...searchOptions, record, maxCandidates, recordExternal});
54
+ async function prepareSearch({record, recordExternal = {recordSource: 'incomingRecord', label: 'ic'}}) {
55
+
56
+ const {search} = await createSearchInterface({...searchOptions, record, maxCandidates, recordExternal});
55
57
  return iterate({});
56
58
 
57
59
  // candidateCount : amount of candidate records retrived from SRU for matching, NOT including current record set
@@ -365,5 +367,5 @@ export default ({detection: detectionOptions, search: searchOptions, maxMatches
365
367
  return true;
366
368
  }
367
369
  }
368
- };
370
+ }
369
371
  };