@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.
- package/dist/candidate-search/choose-queries.js +150 -0
- package/dist/candidate-search/choose-queries.js.map +1 -0
- package/dist/candidate-search/index.js +36 -52
- package/dist/candidate-search/index.js.map +1 -1
- package/dist/candidate-search/index.spec.js +25 -8
- package/dist/candidate-search/index.spec.js.map +1 -1
- package/dist/candidate-search/query-list/bib.js +9 -8
- package/dist/candidate-search/query-list/bib.js.map +1 -1
- package/dist/index.js +7 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/candidate-search/choose-queries.js +123 -0
- package/src/candidate-search/index.js +20 -53
- package/src/candidate-search/index.spec.js +17 -3
- package/src/candidate-search/query-list/bib.js +3 -2
- package/src/index.js +5 -3
|
@@ -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 =
|
|
81
|
+
const chosenQueryList = await filterQueryList({queryList, queryListType});
|
|
82
|
+
debug(`Chosen queries: ${JSON.stringify(chosenQueryList)}`);
|
|
71
83
|
|
|
72
|
-
|
|
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
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
52
|
+
return prepareSearch;
|
|
53
53
|
|
|
54
|
-
|
|
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
|
};
|