@natlibfi/melinda-record-matching 1.0.10 → 2.0.1
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/candidate-search-utils.js +3 -2
- package/dist/candidate-search/candidate-search-utils.js.map +1 -1
- package/dist/candidate-search/index.js +16 -5
- package/dist/candidate-search/index.js.map +1 -1
- package/dist/candidate-search/index.spec.js +2 -2
- package/dist/candidate-search/index.spec.js.map +1 -1
- package/dist/candidate-search/query-list/bib.js +18 -7
- package/dist/candidate-search/query-list/bib.js.map +1 -1
- package/dist/candidate-search/query-list/bib.spec.js +2 -2
- package/dist/candidate-search/query-list/bib.spec.js.map +1 -1
- package/dist/candidate-search/query-list/index.js +3 -3
- package/dist/candidate-search/query-list/index.js.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/index.spec.js +2 -2
- package/dist/index.spec.js.map +1 -1
- package/dist/match-detection/features/bib/all-source-ids.js.map +1 -1
- package/dist/match-detection/features/bib/authors.js.map +1 -1
- package/dist/match-detection/features/bib/bibliographic-level.js.map +1 -1
- package/dist/match-detection/features/bib/host-component.js.map +1 -1
- package/dist/match-detection/features/bib/index.js +24 -24
- package/dist/match-detection/features/bib/index.spec.js +2 -2
- package/dist/match-detection/features/bib/index.spec.js.map +1 -1
- package/dist/match-detection/features/bib/isbn.js.map +1 -1
- package/dist/match-detection/features/bib/issn.js.map +1 -1
- package/dist/match-detection/features/bib/language.js.map +1 -1
- package/dist/match-detection/features/bib/melinda-id.js.map +1 -1
- package/dist/match-detection/features/bib/melinda-identifier-factory.js.map +1 -1
- package/dist/match-detection/features/bib/other-standard-identifier.js.map +1 -1
- package/dist/match-detection/features/bib/publication-time.js.map +1 -1
- package/dist/match-detection/features/bib/record-type.js.map +1 -1
- package/dist/match-detection/features/bib/standard-identifier-factory.js.map +1 -1
- package/dist/match-detection/features/bib/title.js.map +1 -1
- package/dist/match-detection/features/index.js +2 -2
- package/dist/match-detection/index.js +2 -2
- package/dist/match-detection/index.js.map +1 -1
- package/dist/match-detection/index.spec.js +2 -2
- package/dist/match-detection/index.spec.js.map +1 -1
- package/dist/matching-utils.js +1 -1
- package/dist/matching-utils.js.map +1 -1
- package/package.json +26 -29
- package/src/candidate-search/candidate-search-utils.js +3 -1
- package/src/candidate-search/index.js +11 -1
- package/src/candidate-search/query-list/bib.js +15 -1
package/package.json
CHANGED
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
"url": "git@github.com:natlibfi/melinda-record-matching-js.git"
|
|
15
15
|
},
|
|
16
16
|
"license": "LGPL-3.0+",
|
|
17
|
-
"version": "
|
|
17
|
+
"version": "2.0.1",
|
|
18
18
|
"main": "./dist/index.js",
|
|
19
19
|
"engines": {
|
|
20
|
-
"node": ">=
|
|
20
|
+
"node": ">=14"
|
|
21
21
|
},
|
|
22
22
|
"publishConfig": {
|
|
23
23
|
"access": "public"
|
|
@@ -35,35 +35,34 @@
|
|
|
35
35
|
"watch:test": "cross-env DEBUG=1 NODE_ENV=test nodemon -w src -w test-fixtures --exec 'npm run test:dev'"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@natlibfi/marc-record": "^
|
|
39
|
-
"@natlibfi/marc-record-serializers": "^
|
|
40
|
-
"@natlibfi/sru-client": "^
|
|
41
|
-
"debug": "^4.
|
|
42
|
-
"moment": "^2.
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"uuid": "^8.3.0",
|
|
38
|
+
"@natlibfi/marc-record": "^7.0.0",
|
|
39
|
+
"@natlibfi/marc-record-serializers": "^8.0.4",
|
|
40
|
+
"@natlibfi/sru-client": "^5.0.0",
|
|
41
|
+
"debug": "^4.3.3",
|
|
42
|
+
"moment": "^2.29.1",
|
|
43
|
+
"natural": "^5.1.11",
|
|
44
|
+
"uuid": "^8.3.2",
|
|
46
45
|
"winston": "^3.3.3"
|
|
47
46
|
},
|
|
48
47
|
"devDependencies": {
|
|
49
|
-
"@babel/cli": "^7.
|
|
50
|
-
"@babel/core": "^7.
|
|
51
|
-
"@babel/node": "^7.
|
|
52
|
-
"@babel/preset-env": "^7.
|
|
53
|
-
"@babel/register": "^7.
|
|
54
|
-
"@
|
|
55
|
-
"@natlibfi/
|
|
56
|
-
"@natlibfi/fixugen
|
|
57
|
-
"@natlibfi/
|
|
58
|
-
"
|
|
59
|
-
"babel-plugin-istanbul": "^6.
|
|
48
|
+
"@babel/cli": "^7.16.0",
|
|
49
|
+
"@babel/core": "^7.16.0",
|
|
50
|
+
"@babel/node": "^7.16.0",
|
|
51
|
+
"@babel/preset-env": "^7.16.4",
|
|
52
|
+
"@babel/register": "^7.16.0",
|
|
53
|
+
"@babel/eslint-parser": "^7.16.3",
|
|
54
|
+
"@natlibfi/eslint-config-melinda-backend": "^1.1.1",
|
|
55
|
+
"@natlibfi/fixugen": "^1.0.2",
|
|
56
|
+
"@natlibfi/fixugen-http-client": "^1.1.3",
|
|
57
|
+
"@natlibfi/fixura": "^2.2.1",
|
|
58
|
+
"babel-plugin-istanbul": "^6.1.1",
|
|
60
59
|
"babel-plugin-rewire": "^1.2.0",
|
|
61
|
-
"chai": "^4.
|
|
60
|
+
"chai": "^4.3.4",
|
|
62
61
|
"chai-as-promised": "^7.1.1",
|
|
63
|
-
"cross-env": "^7.0.
|
|
64
|
-
"eslint": "^7.
|
|
65
|
-
"mocha": "^
|
|
66
|
-
"nodemon": "^2.0.
|
|
62
|
+
"cross-env": "^7.0.3",
|
|
63
|
+
"eslint": "^7.32.0",
|
|
64
|
+
"mocha": "^9.1.3",
|
|
65
|
+
"nodemon": "^2.0.15",
|
|
67
66
|
"nyc": "^15.1.0"
|
|
68
67
|
},
|
|
69
68
|
"eslintConfig": {
|
|
@@ -74,9 +73,7 @@
|
|
|
74
73
|
[
|
|
75
74
|
"@babel/preset-env",
|
|
76
75
|
{
|
|
77
|
-
"targets":
|
|
78
|
-
"node": "12"
|
|
79
|
-
}
|
|
76
|
+
"targets": "maintained node versions"
|
|
80
77
|
}
|
|
81
78
|
]
|
|
82
79
|
],
|
|
@@ -33,8 +33,10 @@ export function toQueries(identifiers, queryString) {
|
|
|
33
33
|
const debug = createDebugLogger('@natlibfi/melinda-record-matching:toQueries');
|
|
34
34
|
const debugData = debug.extend('data');
|
|
35
35
|
|
|
36
|
+
const quotedIdentifiers = identifiers.map(identifier => identifier.match(/\//u) ? `"${identifier}"` : `${identifier}`);
|
|
37
|
+
|
|
36
38
|
// Aleph supports only two queries with or -operator (This is not actually true)
|
|
37
|
-
const pairs = toPairs(
|
|
39
|
+
const pairs = toPairs(quotedIdentifiers);
|
|
38
40
|
const queries = pairs.map(([a, b]) => b ? `${queryString}=${a} or ${queryString}=${b}` : `${queryString}=${a}`);
|
|
39
41
|
|
|
40
42
|
debugData(`Pairs (${pairs.length}): ${JSON.stringify(pairs)}`);
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
29
|
import createDebugLogger from 'debug';
|
|
30
|
-
import createClient from '@natlibfi/sru-client';
|
|
30
|
+
import createClient, {SruSearchError} from '@natlibfi/sru-client';
|
|
31
31
|
import {MarcRecord} from '@natlibfi/marc-record';
|
|
32
32
|
import {MARCXML} from '@natlibfi/marc-record-serializers';
|
|
33
33
|
import generateQueryList from './query-list';
|
|
@@ -48,6 +48,7 @@ export default ({record, searchSpec, url, maxRecordsPerRequest = 50}) => {
|
|
|
48
48
|
retrieveAll: false
|
|
49
49
|
});
|
|
50
50
|
|
|
51
|
+
debug(`Searching matches for ${inputRecordId}`);
|
|
51
52
|
debug(`Generated queryList ${JSON.stringify(queryList)}`);
|
|
52
53
|
if (queryList.length === 0) { // eslint-disable-line functional/no-conditional-statement
|
|
53
54
|
throw new CandidateSearchError(`Generated query list contains no queries`);
|
|
@@ -79,6 +80,12 @@ export default ({record, searchSpec, url, maxRecordsPerRequest = 50}) => {
|
|
|
79
80
|
|
|
80
81
|
client.searchRetrieve(query, {startRecord: resultSetOffset})
|
|
81
82
|
.on('error', err => {
|
|
83
|
+
// eslint-disable-next-line functional/no-conditional-statement
|
|
84
|
+
if (err instanceof SruSearchError) {
|
|
85
|
+
debug(`SRU SruSearchError for query: ${query}: ${err}`);
|
|
86
|
+
reject(new CandidateSearchError(`SRU SruSearchError for query: ${query}: ${err}`));
|
|
87
|
+
}
|
|
88
|
+
debug(`SRU error for query: ${query}: ${err}`);
|
|
82
89
|
reject(new CandidateSearchError(`SRU error for query: ${query}: ${err}`));
|
|
83
90
|
})
|
|
84
91
|
.on('end', async nextOffset => {
|
|
@@ -101,6 +108,9 @@ export default ({record, searchSpec, url, maxRecordsPerRequest = 50}) => {
|
|
|
101
108
|
const foundRecordMarc = await MARCXML.from(foundRecord, {subfieldValues: false});
|
|
102
109
|
const foundRecordId = getRecordId(foundRecordMarc);
|
|
103
110
|
|
|
111
|
+
// This does not work and might cause problems:
|
|
112
|
+
// Record *should* match itself AND in REST the input record is given id 000000001 always
|
|
113
|
+
debug(`Checking ${inputRecordId} vs ${foundRecordId}`);
|
|
104
114
|
if (inputRecordId === foundRecordId) {
|
|
105
115
|
debug(`Input and candidate are the same record per 001. Discarding candidate`);
|
|
106
116
|
return;
|
|
@@ -39,12 +39,15 @@ export function bibSourceIds(record) {
|
|
|
39
39
|
SID__ $c 123457 $b helka
|
|
40
40
|
SID__ $c (ANDL100020)1077305 $b sata
|
|
41
41
|
SID__ $c VER999999 $ FI-KV
|
|
42
|
+
SID__ $c /10024/508126 $ REPO_THESEUS
|
|
42
43
|
|
|
43
44
|
In melinda.sourceid -index case is kept, sourceprefixes in brackets and hyphens are normalized away:
|
|
45
|
+
Note: slashes are not normalized away, but a SRU-search-string including slashes needs to be quoted
|
|
44
46
|
|
|
45
47
|
1234567helka
|
|
46
48
|
1077305sata
|
|
47
49
|
VER999999FIKV
|
|
50
|
+
/10024/508126REPO_THESEUS
|
|
48
51
|
|
|
49
52
|
Note: All Melinda records that have a matching records in a local db do NOT have SID for that local records,
|
|
50
53
|
existence of a SID field depends on how the record has been added to Melinda and how it has been handled
|
|
@@ -56,6 +59,8 @@ export function bibSourceIds(record) {
|
|
|
56
59
|
|
|
57
60
|
const debug = createDebugLogger('@natlibfi/melinda-record-matching:candidate-search:query:source-ids');
|
|
58
61
|
const debugData = debug.extend('data');
|
|
62
|
+
//const debugInfo = debug.extend('info');
|
|
63
|
+
|
|
59
64
|
debug(`Creating queries for sourceid's`);
|
|
60
65
|
|
|
61
66
|
const fSids = record.get('SID');
|
|
@@ -168,12 +173,20 @@ export function bibHostComponents(record) {
|
|
|
168
173
|
}
|
|
169
174
|
}
|
|
170
175
|
|
|
176
|
+
// SRU search dc.title with a search phrase starting with ^ maps currently in Melinda to
|
|
177
|
+
// (probably) to *headings* index TIT
|
|
178
|
+
// Headings index TIT drops articles etc. from the start of the title according to the filing indicator
|
|
179
|
+
// Currently filing indicator is not implemented - if the title starts with an article and the Melinda
|
|
180
|
+
// record is correctly catalogued using a filing indicator -> dc.title search won't match
|
|
181
|
+
|
|
171
182
|
export function bibTitle(record) {
|
|
172
183
|
const title = getTitle();
|
|
173
184
|
|
|
174
185
|
if (title) {
|
|
175
186
|
const formatted = title
|
|
176
187
|
.replace(/[^\w\s\p{Alphabetic}]/gu, '')
|
|
188
|
+
// Clean up concurrent spaces from fe. subfield changes
|
|
189
|
+
.replace(/ +/gu, ' ')
|
|
177
190
|
.trim()
|
|
178
191
|
.slice(0, 30)
|
|
179
192
|
.trim();
|
|
@@ -191,7 +204,8 @@ export function bibTitle(record) {
|
|
|
191
204
|
return field.subfields
|
|
192
205
|
.filter(({code}) => ['a', 'b'].includes(code))
|
|
193
206
|
.map(({value}) => value)
|
|
194
|
-
|
|
207
|
+
// In Melinda's index subfield separators are indexed as ' '
|
|
208
|
+
.join(' ');
|
|
195
209
|
}
|
|
196
210
|
return false;
|
|
197
211
|
}
|