@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.
Files changed (44) hide show
  1. package/dist/candidate-search/candidate-search-utils.js +3 -2
  2. package/dist/candidate-search/candidate-search-utils.js.map +1 -1
  3. package/dist/candidate-search/index.js +16 -5
  4. package/dist/candidate-search/index.js.map +1 -1
  5. package/dist/candidate-search/index.spec.js +2 -2
  6. package/dist/candidate-search/index.spec.js.map +1 -1
  7. package/dist/candidate-search/query-list/bib.js +18 -7
  8. package/dist/candidate-search/query-list/bib.js.map +1 -1
  9. package/dist/candidate-search/query-list/bib.spec.js +2 -2
  10. package/dist/candidate-search/query-list/bib.spec.js.map +1 -1
  11. package/dist/candidate-search/query-list/index.js +3 -3
  12. package/dist/candidate-search/query-list/index.js.map +1 -1
  13. package/dist/index.js +3 -3
  14. package/dist/index.js.map +1 -1
  15. package/dist/index.spec.js +2 -2
  16. package/dist/index.spec.js.map +1 -1
  17. package/dist/match-detection/features/bib/all-source-ids.js.map +1 -1
  18. package/dist/match-detection/features/bib/authors.js.map +1 -1
  19. package/dist/match-detection/features/bib/bibliographic-level.js.map +1 -1
  20. package/dist/match-detection/features/bib/host-component.js.map +1 -1
  21. package/dist/match-detection/features/bib/index.js +24 -24
  22. package/dist/match-detection/features/bib/index.spec.js +2 -2
  23. package/dist/match-detection/features/bib/index.spec.js.map +1 -1
  24. package/dist/match-detection/features/bib/isbn.js.map +1 -1
  25. package/dist/match-detection/features/bib/issn.js.map +1 -1
  26. package/dist/match-detection/features/bib/language.js.map +1 -1
  27. package/dist/match-detection/features/bib/melinda-id.js.map +1 -1
  28. package/dist/match-detection/features/bib/melinda-identifier-factory.js.map +1 -1
  29. package/dist/match-detection/features/bib/other-standard-identifier.js.map +1 -1
  30. package/dist/match-detection/features/bib/publication-time.js.map +1 -1
  31. package/dist/match-detection/features/bib/record-type.js.map +1 -1
  32. package/dist/match-detection/features/bib/standard-identifier-factory.js.map +1 -1
  33. package/dist/match-detection/features/bib/title.js.map +1 -1
  34. package/dist/match-detection/features/index.js +2 -2
  35. package/dist/match-detection/index.js +2 -2
  36. package/dist/match-detection/index.js.map +1 -1
  37. package/dist/match-detection/index.spec.js +2 -2
  38. package/dist/match-detection/index.spec.js.map +1 -1
  39. package/dist/matching-utils.js +1 -1
  40. package/dist/matching-utils.js.map +1 -1
  41. package/package.json +26 -29
  42. package/src/candidate-search/candidate-search-utils.js +3 -1
  43. package/src/candidate-search/index.js +11 -1
  44. 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": "1.0.10",
17
+ "version": "2.0.1",
18
18
  "main": "./dist/index.js",
19
19
  "engines": {
20
- "node": ">=12"
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": "^6.1.1",
39
- "@natlibfi/marc-record-serializers": "^7.2.3",
40
- "@natlibfi/sru-client": "^4.0.0",
41
- "debug": "^4.1.1",
42
- "moment": "^2.28.0",
43
- "mongodb": "^3.6.2",
44
- "natural": "^2.1.5",
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.11.6",
50
- "@babel/core": "^7.11.6",
51
- "@babel/node": "^7.10.5",
52
- "@babel/preset-env": "^7.11.5",
53
- "@babel/register": "^7.11.5",
54
- "@natlibfi/eslint-config-melinda-backend": "^1.0.5",
55
- "@natlibfi/fixugen": "^1.0.0",
56
- "@natlibfi/fixugen-http-client": "^1.1.1",
57
- "@natlibfi/fixura": "^2.1.3",
58
- "babel-eslint": "^10.1.0",
59
- "babel-plugin-istanbul": "^6.0.0",
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.2.0",
60
+ "chai": "^4.3.4",
62
61
  "chai-as-promised": "^7.1.1",
63
- "cross-env": "^7.0.2",
64
- "eslint": "^7.9.0",
65
- "mocha": "^8.1.3",
66
- "nodemon": "^2.0.4",
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(identifiers);
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
- .join('');
207
+ // In Melinda's index subfield separators are indexed as ' '
208
+ .join(' ');
195
209
  }
196
210
  return false;
197
211
  }