@natlibfi/melinda-record-matching 2.0.1 → 2.0.7-alpha.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 (96) hide show
  1. package/.github/CODEOWNERS +2 -0
  2. package/.github/dependabot.yml +40 -0
  3. package/.github/workflows/melinda-node-tests.yml +70 -0
  4. package/README.md +1 -1
  5. package/dist/candidate-search/candidate-search-utils.js +3 -6
  6. package/dist/candidate-search/candidate-search-utils.js.map +1 -1
  7. package/dist/candidate-search/index.js +115 -50
  8. package/dist/candidate-search/index.js.map +1 -1
  9. package/dist/candidate-search/index.spec.js +41 -48
  10. package/dist/candidate-search/index.spec.js.map +1 -1
  11. package/dist/candidate-search/query-list/bib.js +154 -64
  12. package/dist/candidate-search/query-list/bib.js.map +1 -1
  13. package/dist/candidate-search/query-list/bib.spec.js +1 -10
  14. package/dist/candidate-search/query-list/bib.spec.js.map +1 -1
  15. package/dist/candidate-search/query-list/index.js +4 -10
  16. package/dist/candidate-search/query-list/index.js.map +1 -1
  17. package/dist/index.js +498 -50
  18. package/dist/index.js.map +1 -1
  19. package/dist/index.spec.js +60 -34
  20. package/dist/index.spec.js.map +1 -1
  21. package/dist/match-detection/features/bib/all-source-ids.js +16 -19
  22. package/dist/match-detection/features/bib/all-source-ids.js.map +1 -1
  23. package/dist/match-detection/features/bib/authors.js +31 -35
  24. package/dist/match-detection/features/bib/authors.js.map +1 -1
  25. package/dist/match-detection/features/bib/bibliographic-level.js +3 -3
  26. package/dist/match-detection/features/bib/bibliographic-level.js.map +1 -1
  27. package/dist/match-detection/features/bib/host-component.js +3 -3
  28. package/dist/match-detection/features/bib/host-component.js.map +1 -1
  29. package/dist/match-detection/features/bib/index.js +28 -13
  30. package/dist/match-detection/features/bib/index.js.map +1 -1
  31. package/dist/match-detection/features/bib/index.spec.js +9 -13
  32. package/dist/match-detection/features/bib/index.spec.js.map +1 -1
  33. package/dist/match-detection/features/bib/isbn.js +28 -6
  34. package/dist/match-detection/features/bib/isbn.js.map +1 -1
  35. package/dist/match-detection/features/bib/issn.js +0 -4
  36. package/dist/match-detection/features/bib/issn.js.map +1 -1
  37. package/dist/match-detection/features/bib/language.js +69 -41
  38. package/dist/match-detection/features/bib/language.js.map +1 -1
  39. package/dist/match-detection/features/bib/media-type.js +83 -0
  40. package/dist/match-detection/features/bib/media-type.js.map +1 -0
  41. package/dist/match-detection/features/bib/melinda-id.js +0 -4
  42. package/dist/match-detection/features/bib/melinda-id.js.map +1 -1
  43. package/dist/match-detection/features/bib/melinda-identifier-factory.js +6 -17
  44. package/dist/match-detection/features/bib/melinda-identifier-factory.js.map +1 -1
  45. package/dist/match-detection/features/bib/other-standard-identifier.js +1 -4
  46. package/dist/match-detection/features/bib/other-standard-identifier.js.map +1 -1
  47. package/dist/match-detection/features/bib/publication-time-allow-cons-years-multi.js +256 -0
  48. package/dist/match-detection/features/bib/publication-time-allow-cons-years-multi.js.map +1 -0
  49. package/dist/match-detection/features/bib/publication-time-allow-cons-years.js +71 -0
  50. package/dist/match-detection/features/bib/publication-time-allow-cons-years.js.map +1 -0
  51. package/dist/match-detection/features/bib/publication-time.js +9 -8
  52. package/dist/match-detection/features/bib/publication-time.js.map +1 -1
  53. package/dist/match-detection/features/bib/record-type.js +6 -3
  54. package/dist/match-detection/features/bib/record-type.js.map +1 -1
  55. package/dist/match-detection/features/bib/standard-identifier-factory.js +129 -39
  56. package/dist/match-detection/features/bib/standard-identifier-factory.js.map +1 -1
  57. package/dist/match-detection/features/bib/title-version-original.js +79 -0
  58. package/dist/match-detection/features/bib/title-version-original.js.map +1 -0
  59. package/dist/match-detection/features/bib/title.js +29 -22
  60. package/dist/match-detection/features/bib/title.js.map +1 -1
  61. package/dist/match-detection/features/index.js +0 -4
  62. package/dist/match-detection/features/index.js.map +1 -1
  63. package/dist/match-detection/index.js +94 -47
  64. package/dist/match-detection/index.js.map +1 -1
  65. package/dist/match-detection/index.spec.js +25 -15
  66. package/dist/match-detection/index.spec.js.map +1 -1
  67. package/dist/matching-utils.js +63 -15
  68. package/dist/matching-utils.js.map +1 -1
  69. package/package.json +27 -24
  70. package/src/candidate-search/index.js +93 -31
  71. package/src/candidate-search/index.spec.js +27 -24
  72. package/src/candidate-search/query-list/bib.js +149 -22
  73. package/src/candidate-search/query-list/index.js +1 -1
  74. package/src/index.js +310 -38
  75. package/src/index.spec.js +49 -21
  76. package/src/match-detection/features/bib/all-source-ids.js +3 -3
  77. package/src/match-detection/features/bib/authors.js +23 -16
  78. package/src/match-detection/features/bib/bibliographic-level.js +1 -1
  79. package/src/match-detection/features/bib/host-component.js +1 -1
  80. package/src/match-detection/features/bib/index.js +4 -0
  81. package/src/match-detection/features/bib/index.spec.js +10 -2
  82. package/src/match-detection/features/bib/isbn.js +21 -2
  83. package/src/match-detection/features/bib/language.js +63 -22
  84. package/src/match-detection/features/bib/media-type.js +77 -0
  85. package/src/match-detection/features/bib/melinda-identifier-factory.js +2 -3
  86. package/src/match-detection/features/bib/other-standard-identifier.js +2 -0
  87. package/src/match-detection/features/bib/publication-time-allow-cons-years-multi.js +268 -0
  88. package/src/match-detection/features/bib/publication-time-allow-cons-years.js +67 -0
  89. package/src/match-detection/features/bib/publication-time.js +9 -4
  90. package/src/match-detection/features/bib/record-type.js +5 -1
  91. package/src/match-detection/features/bib/standard-identifier-factory.js +107 -22
  92. package/src/match-detection/features/bib/title-version-original.js +78 -0
  93. package/src/match-detection/features/bib/title.js +27 -7
  94. package/src/match-detection/index.js +60 -22
  95. package/src/match-detection/index.spec.js +18 -4
  96. package/src/matching-utils.js +62 -5
@@ -4,20 +4,17 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
-
8
- var _debug = _interopRequireDefault(require("debug"));
9
-
10
7
  var _natural = require("natural");
11
-
8
+ var _matchingUtils = require("../../../matching-utils");
9
+ var _debug = _interopRequireDefault(require("debug"));
12
10
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
-
14
11
  /**
15
12
  *
16
13
  * @licstart The following is the entire license notice for the JavaScript code in this file.
17
14
  *
18
15
  * Melinda record matching modules for Javascript
19
16
  *
20
- * Copyright (C) 2020 University Of Helsinki (The National Library Of Finland)
17
+ * Copyright (C) 2020-2022 University Of Helsinki (The National Library Of Finland)
21
18
  *
22
19
  * This file is part of melinda-record-matching-js
23
20
  *
@@ -38,54 +35,64 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
38
35
  * for the JavaScript code in this file.
39
36
  *
40
37
  */
38
+
39
+ const debug = (0, _debug.default)('@natlibfi/melinda-record-matching:match-detection:features:title');
40
+ const debugData = debug.extend('data');
41
41
  var _default = ({
42
42
  treshold = 10
43
43
  } = {}) => ({
44
44
  name: 'Title',
45
- extract: record => {
45
+ extract: ({
46
+ record,
47
+ recordExternal
48
+ }) => {
49
+ const label = recordExternal && recordExternal.label ? recordExternal.label : 'record';
46
50
  const title = getTitle();
47
-
48
- if (title) {
49
- return [title.replace(/[^\p{Letter}\p{Number}]/gu, '').toLowerCase()];
51
+ debug(`${label} title: ${title}`);
52
+ if ((0, _matchingUtils.testStringOrNumber)(title)) {
53
+ const titleAsNormalizedString = String(title)
54
+ // decompose unicode diacritics
55
+ .normalize('NFD')
56
+ // strip non-letters/numbers
57
+ // - note: combined with decomposing unicode diactics this normalizes both 'saa' and 'sää' as 'saa'
58
+ // - we could precompose the finnish letters back to avoid this
59
+ .replace(/[^\p{Letter}\p{Number}]/gu, '').toLowerCase();
60
+ debug(`${label} titleString: ${titleAsNormalizedString}`);
61
+ return [titleAsNormalizedString];
50
62
  }
51
-
52
63
  return [];
53
-
54
64
  function getTitle() {
55
65
  const [field] = record.get(/^245$/u);
56
-
66
+ debugData(`${label} titleField: ${JSON.stringify(field)}`);
57
67
  if (field) {
58
- return field.subfields.filter(({
68
+ return field.subfields
69
+ // get also $n:s and $p:s here
70
+ .filter(({
59
71
  code
60
- }) => ['a', 'b'].includes(code)).map(({
72
+ }) => ['a', 'b', 'n', 'p'].includes(code)).map(({
61
73
  value
62
- }) => value).join('');
74
+ }) => (0, _matchingUtils.testStringOrNumber)(value) ? String(value) : '').join('');
63
75
  }
76
+ return false;
64
77
  }
65
78
  },
66
79
  compare: (a, b) => {
67
80
  const debug = (0, _debug.default)('@natlibfi/melinda-record-matching:match-detection:features/bib/title');
68
81
  const distance = (0, _natural.LevenshteinDistance)(a[0], b[0]);
69
-
70
82
  if (distance === 0) {
71
83
  return 0.5;
72
84
  }
73
-
74
85
  const maxLength = getMaxLength();
75
86
  const percentage = distance / maxLength * 100;
76
87
  debug(`'${a}' vs '${b}': Max length = ${maxLength}, distance = ${distance}, percentage = ${percentage}`);
77
-
78
88
  if (percentage <= treshold) {
79
89
  return 0.3;
80
90
  }
81
-
82
91
  return -0.5;
83
-
84
92
  function getMaxLength() {
85
93
  return a[0].length > b[0].length ? a[0].length : b[0].length;
86
94
  }
87
95
  }
88
96
  });
89
-
90
97
  exports.default = _default;
91
98
  //# sourceMappingURL=title.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/match-detection/features/bib/title.js"],"names":["treshold","name","extract","record","title","getTitle","replace","toLowerCase","field","get","subfields","filter","code","includes","map","value","join","compare","a","b","debug","distance","maxLength","getMaxLength","percentage","length"],"mappings":";;;;;;;AA4BA;;AACA;;;;AA7BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;eAKe,CAAC;AAACA,EAAAA,QAAQ,GAAG;AAAZ,IAAkB,EAAnB,MAA2B;AACxCC,EAAAA,IAAI,EAAE,OADkC;AAExCC,EAAAA,OAAO,EAAEC,MAAM,IAAI;AACjB,UAAMC,KAAK,GAAGC,QAAQ,EAAtB;;AAEA,QAAID,KAAJ,EAAW;AACT,aAAO,CAACA,KAAK,CAACE,OAAN,CAAc,2BAAd,EAA2C,EAA3C,EAA+CC,WAA/C,EAAD,CAAP;AACD;;AAED,WAAO,EAAP;;AAEA,aAASF,QAAT,GAAoB;AAClB,YAAM,CAACG,KAAD,IAAUL,MAAM,CAACM,GAAP,CAAW,QAAX,CAAhB;;AAEA,UAAID,KAAJ,EAAW;AACT,eAAOA,KAAK,CAACE,SAAN,CACJC,MADI,CACG,CAAC;AAACC,UAAAA;AAAD,SAAD,KAAY,CAAC,GAAD,EAAM,GAAN,EAAWC,QAAX,CAAoBD,IAApB,CADf,EAEJE,GAFI,CAEA,CAAC;AAACC,UAAAA;AAAD,SAAD,KAAaA,KAFb,EAGJC,IAHI,CAGC,EAHD,CAAP;AAID;AACF;AACF,GArBuC;AAsBxCC,EAAAA,OAAO,EAAE,CAACC,CAAD,EAAIC,CAAJ,KAAU;AACjB,UAAMC,KAAK,GAAG,oBAAkB,sEAAlB,CAAd;AACA,UAAMC,QAAQ,GAAG,kCAAMH,CAAC,CAAC,CAAD,CAAP,EAAYC,CAAC,CAAC,CAAD,CAAb,CAAjB;;AAEA,QAAIE,QAAQ,KAAK,CAAjB,EAAoB;AAClB,aAAO,GAAP;AACD;;AAED,UAAMC,SAAS,GAAGC,YAAY,EAA9B;AACA,UAAMC,UAAU,GAAGH,QAAQ,GAAGC,SAAX,GAAuB,GAA1C;AAEAF,IAAAA,KAAK,CAAE,IAAGF,CAAE,SAAQC,CAAE,mBAAkBG,SAAU,gBAAeD,QAAS,kBAAiBG,UAAW,EAAjG,CAAL;;AAEA,QAAIA,UAAU,IAAIxB,QAAlB,EAA4B;AAC1B,aAAO,GAAP;AACD;;AAED,WAAO,CAAC,GAAR;;AAEA,aAASuB,YAAT,GAAwB;AACtB,aAAOL,CAAC,CAAC,CAAD,CAAD,CAAKO,MAAL,GAAcN,CAAC,CAAC,CAAD,CAAD,CAAKM,MAAnB,GAA4BP,CAAC,CAAC,CAAD,CAAD,CAAKO,MAAjC,GAA0CN,CAAC,CAAC,CAAD,CAAD,CAAKM,MAAtD;AACD;AAEF;AA7CuC,CAA3B,C","sourcesContent":["/**\n*\n* @licstart The following is the entire license notice for the JavaScript code in this file.\n*\n* Melinda record matching modules for Javascript\n*\n* Copyright (C) 2020 University Of Helsinki (The National Library Of Finland)\n*\n* This file is part of melinda-record-matching-js\n*\n* melinda-record-matching-js program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Lesser General Public License as\n* published by the Free Software Foundation, either version 3 of the\n* License, or (at your option) any later version.\n*\n* melinda-record-matching-js is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n* GNU Lesser General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. If not, see <http://www.gnu.org/licenses/>.\n*\n* @licend The above is the entire license notice\n* for the JavaScript code in this file.\n*\n*/\n\nimport createDebugLogger from 'debug';\nimport {LevenshteinDistance as leven} from 'natural';\n\nexport default ({treshold = 10} = {}) => ({\n name: 'Title',\n extract: record => {\n const title = getTitle();\n\n if (title) {\n return [title.replace(/[^\\p{Letter}\\p{Number}]/gu, '').toLowerCase()];\n }\n\n return [];\n\n function getTitle() {\n const [field] = record.get(/^245$/u);\n\n if (field) {\n return field.subfields\n .filter(({code}) => ['a', 'b'].includes(code))\n .map(({value}) => value)\n .join('');\n }\n }\n },\n compare: (a, b) => {\n const debug = createDebugLogger('@natlibfi/melinda-record-matching:match-detection:features/bib/title');\n const distance = leven(a[0], b[0]);\n\n if (distance === 0) {\n return 0.5;\n }\n\n const maxLength = getMaxLength();\n const percentage = distance / maxLength * 100;\n\n debug(`'${a}' vs '${b}': Max length = ${maxLength}, distance = ${distance}, percentage = ${percentage}`);\n\n if (percentage <= treshold) {\n return 0.3;\n }\n\n return -0.5;\n\n function getMaxLength() {\n return a[0].length > b[0].length ? a[0].length : b[0].length;\n }\n\n }\n});\n"],"file":"title.js"}
1
+ {"version":3,"file":"title.js","names":["_natural","require","_matchingUtils","_debug","_interopRequireDefault","obj","__esModule","default","debug","createDebugLogger","debugData","extend","_default","treshold","name","extract","record","recordExternal","label","title","getTitle","testStringOrNumber","titleAsNormalizedString","String","normalize","replace","toLowerCase","field","get","JSON","stringify","subfields","filter","code","includes","map","value","join","compare","a","b","distance","leven","maxLength","getMaxLength","percentage","length","exports"],"sources":["../../../../src/match-detection/features/bib/title.js"],"sourcesContent":["/**\n*\n* @licstart The following is the entire license notice for the JavaScript code in this file.\n*\n* Melinda record matching modules for Javascript\n*\n* Copyright (C) 2020-2022 University Of Helsinki (The National Library Of Finland)\n*\n* This file is part of melinda-record-matching-js\n*\n* melinda-record-matching-js program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Lesser General Public License as\n* published by the Free Software Foundation, either version 3 of the\n* License, or (at your option) any later version.\n*\n* melinda-record-matching-js is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n* GNU Lesser General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. If not, see <http://www.gnu.org/licenses/>.\n*\n* @licend The above is the entire license notice\n* for the JavaScript code in this file.\n*\n*/\n\n\nimport {LevenshteinDistance as leven} from 'natural';\nimport {testStringOrNumber} from '../../../matching-utils';\nimport createDebugLogger from 'debug';\n\nconst debug = createDebugLogger('@natlibfi/melinda-record-matching:match-detection:features:title');\nconst debugData = debug.extend('data');\n\n\nexport default ({treshold = 10} = {}) => ({\n name: 'Title',\n extract: ({record, recordExternal}) => {\n const label = recordExternal && recordExternal.label ? recordExternal.label : 'record';\n const title = getTitle();\n debug(`${label} title: ${title}`);\n\n if (testStringOrNumber(title)) {\n const titleAsNormalizedString = String(title)\n // decompose unicode diacritics\n .normalize('NFD')\n // strip non-letters/numbers\n // - note: combined with decomposing unicode diactics this normalizes both 'saa' and 'sää' as 'saa'\n // - we could precompose the finnish letters back to avoid this\n .replace(/[^\\p{Letter}\\p{Number}]/gu, '')\n .toLowerCase();\n debug(`${label} titleString: ${titleAsNormalizedString}`);\n return [titleAsNormalizedString];\n }\n\n return [];\n\n function getTitle() {\n const [field] = record.get(/^245$/u);\n debugData(`${label} titleField: ${JSON.stringify(field)}`);\n\n if (field) {\n return field.subfields\n // get also $n:s and $p:s here\n .filter(({code}) => ['a', 'b', 'n', 'p'].includes(code))\n .map(({value}) => testStringOrNumber(value) ? String(value) : '')\n .join('');\n }\n return false;\n }\n },\n compare: (a, b) => {\n const debug = createDebugLogger('@natlibfi/melinda-record-matching:match-detection:features/bib/title');\n const distance = leven(a[0], b[0]);\n\n if (distance === 0) {\n return 0.5;\n }\n\n const maxLength = getMaxLength();\n const percentage = distance / maxLength * 100;\n\n debug(`'${a}' vs '${b}': Max length = ${maxLength}, distance = ${distance}, percentage = ${percentage}`);\n\n if (percentage <= treshold) {\n return 0.3;\n }\n\n return -0.5;\n\n function getMaxLength() {\n return a[0].length > b[0].length ? a[0].length : b[0].length;\n }\n\n }\n});\n"],"mappings":"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"}
@@ -4,12 +4,8 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.bib = void 0;
7
-
8
7
  var bib = _interopRequireWildcard(require("./bib"));
9
-
10
8
  exports.bib = bib;
11
-
12
9
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
13
-
14
10
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
15
11
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/match-detection/features/index.js"],"names":[],"mappings":";;;;;;;AA4BA","sourcesContent":["/**\n*\n* @licstart The following is the entire license notice for the JavaScript code in this file.\n*\n* Melinda record matching modules for Javascript\n*\n* Copyright (C) 2020 University Of Helsinki (The National Library Of Finland)\n*\n* This file is part of melinda-record-matching-js\n*\n* melinda-record-matching-js program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Lesser General Public License as\n* published by the Free Software Foundation, either version 3 of the\n* License, or (at your option) any later version.\n*\n* melinda-record-matching-js is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n* GNU Lesser General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. If not, see <http://www.gnu.org/licenses/>.\n*\n* @licend The above is the entire license notice\n* for the JavaScript code in this file.\n*\n*/\n\nimport * as bib from './bib';\nexport {bib};\n"],"file":"index.js"}
1
+ {"version":3,"file":"index.js","names":["bib","_interopRequireWildcard","require","exports","_getRequireWildcardCache","nodeInterop","WeakMap","cacheBabelInterop","cacheNodeInterop","obj","__esModule","default","cache","has","get","newObj","hasPropertyDescriptor","Object","defineProperty","getOwnPropertyDescriptor","key","prototype","hasOwnProperty","call","desc","set"],"sources":["../../../src/match-detection/features/index.js"],"sourcesContent":["/**\n*\n* @licstart The following is the entire license notice for the JavaScript code in this file.\n*\n* Melinda record matching modules for Javascript\n*\n* Copyright (C) 2020 University Of Helsinki (The National Library Of Finland)\n*\n* This file is part of melinda-record-matching-js\n*\n* melinda-record-matching-js program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Lesser General Public License as\n* published by the Free Software Foundation, either version 3 of the\n* License, or (at your option) any later version.\n*\n* melinda-record-matching-js is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n* GNU Lesser General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. If not, see <http://www.gnu.org/licenses/>.\n*\n* @licend The above is the entire license notice\n* for the JavaScript code in this file.\n*\n*/\n\nimport * as bib from './bib';\nexport {bib};\n"],"mappings":";;;;;;AA4BA,IAAAA,GAAA,GAAAC,uBAAA,CAAAC,OAAA;AAA6BC,OAAA,CAAAH,GAAA,GAAAA,GAAA;AAAA,SAAAI,yBAAAC,WAAA,eAAAC,OAAA,kCAAAC,iBAAA,OAAAD,OAAA,QAAAE,gBAAA,OAAAF,OAAA,YAAAF,wBAAA,YAAAA,CAAAC,WAAA,WAAAA,WAAA,GAAAG,gBAAA,GAAAD,iBAAA,KAAAF,WAAA;AAAA,SAAAJ,wBAAAQ,GAAA,EAAAJ,WAAA,SAAAA,WAAA,IAAAI,GAAA,IAAAA,GAAA,CAAAC,UAAA,WAAAD,GAAA,QAAAA,GAAA,oBAAAA,GAAA,wBAAAA,GAAA,4BAAAE,OAAA,EAAAF,GAAA,UAAAG,KAAA,GAAAR,wBAAA,CAAAC,WAAA,OAAAO,KAAA,IAAAA,KAAA,CAAAC,GAAA,CAAAJ,GAAA,YAAAG,KAAA,CAAAE,GAAA,CAAAL,GAAA,SAAAM,MAAA,WAAAC,qBAAA,GAAAC,MAAA,CAAAC,cAAA,IAAAD,MAAA,CAAAE,wBAAA,WAAAC,GAAA,IAAAX,GAAA,QAAAW,GAAA,kBAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAd,GAAA,EAAAW,GAAA,SAAAI,IAAA,GAAAR,qBAAA,GAAAC,MAAA,CAAAE,wBAAA,CAAAV,GAAA,EAAAW,GAAA,cAAAI,IAAA,KAAAA,IAAA,CAAAV,GAAA,IAAAU,IAAA,CAAAC,GAAA,KAAAR,MAAA,CAAAC,cAAA,CAAAH,MAAA,EAAAK,GAAA,EAAAI,IAAA,YAAAT,MAAA,CAAAK,GAAA,IAAAX,GAAA,CAAAW,GAAA,SAAAL,MAAA,CAAAJ,OAAA,GAAAF,GAAA,MAAAG,KAAA,IAAAA,KAAA,CAAAa,GAAA,CAAAhB,GAAA,EAAAM,MAAA,YAAAA,MAAA"}
@@ -4,21 +4,12 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.features = exports.default = void 0;
7
-
8
7
  var _debug = _interopRequireDefault(require("debug"));
9
-
10
8
  var features = _interopRequireWildcard(require("./features"));
11
-
12
9
  exports.features = features;
13
-
14
10
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
15
-
16
11
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
17
-
18
12
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
-
20
- /* eslint-disable no-console */
21
-
22
13
  /**
23
14
  *
24
15
  * @licstart The following is the entire license notice for the JavaScript code in this file.
@@ -46,52 +37,113 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
46
37
  * for the JavaScript code in this file.
47
38
  *
48
39
  */
49
- // eslint-disable-next-line max-statements
50
40
  var _default = ({
51
41
  strategy,
52
42
  treshold = 0.9
53
- }) => (recordA, recordB) => {
43
+ }, returnStrategy = false, localSettings = {}) => ({
44
+ recordA,
45
+ recordB,
46
+ recordAExternal = {},
47
+ recordBExternal = {}
48
+ }) => {
54
49
  const minProbabilityQuantifier = 0.5;
55
50
  const debug = (0, _debug.default)('@natlibfi/melinda-record-matching:match-detection');
56
51
  const debugData = debug.extend('data');
57
- const featuresA = extractFeatures(recordA);
58
- const featuresB = extractFeatures(recordB);
59
- debugData(`Features (a): ${JSON.stringify(featuresA)}`);
60
- debugData(`Features (b): ${JSON.stringify(featuresB)}`);
61
- const featurePairs = generateFeaturePairs();
62
- const similarityVector = generateSimilarityVector();
63
-
64
- if (similarityVector.some(v => v >= minProbabilityQuantifier)) {
65
- const probability = calculateprobability();
66
- debug(`probability: ${probability} (Treshold: ${treshold})`);
67
- return {
68
- match: probability >= treshold,
69
- probability
70
- };
71
- }
72
-
73
- debugData(`No feature yielded minimum probability amount of points (${minProbabilityQuantifier})`);
74
- return {
75
- match: false,
76
- probability: 0.0
77
- };
78
-
79
- function calculateprobability() {
80
- const probability = similarityVector.reduce((acc, v) => acc + v, 0.0);
81
- return probability > 1.0 ? 1.0 : probability;
52
+ debugData(`Strategy: ${JSON.stringify(strategy)}, Treshold: ${JSON.stringify(treshold)}, ReturnStrategy: ${JSON.stringify(returnStrategy)}`);
53
+ debugData(`Records: A: ${recordA}\nB: ${recordB}`);
54
+ debug(`Externals: A: ${JSON.stringify(recordAExternal)}, B: ${JSON.stringify(recordBExternal)}`);
55
+ // We could add here labels for records if we didn't get external labels
56
+
57
+ const featuresA = extractFeatures({
58
+ record: recordA,
59
+ recordExternal: recordAExternal,
60
+ localSettings
61
+ });
62
+ debug(`We got an array of records: ${Array.isArray(recordB)}`);
63
+ const recordsB = Array.isArray(recordB) ? recordB : [recordB];
64
+ const recordsBExternal = Array.isArray(recordB) ? recordBExternal : [recordBExternal];
65
+ const detectionResults = recordsB.map((record, index) => actualDetection({
66
+ featuresA,
67
+ recordAExternal,
68
+ record,
69
+ recordExternal: recordsBExternal[index],
70
+ index
71
+ }));
72
+
73
+ // if we got array of records, we return an array of result
74
+ // if we got a singular record, we return a singular result
75
+ return Array.isArray(recordB) ? detectionResults : detectionResults[0];
76
+ function actualDetection({
77
+ featuresA,
78
+ record,
79
+ recordExternal,
80
+ index,
81
+ localSettings
82
+ }) {
83
+ const labelA = recordAExternal && recordAExternal.label ? recordAExternal.label : 'a';
84
+ const labelB = recordExternal && recordExternal.label ? recordExternal.label : 'b';
85
+ debug(`Actual detection for record ${index + 1} ${labelB}`);
86
+ const featuresB = extractFeatures({
87
+ record,
88
+ recordExternal,
89
+ localSettings
90
+ });
91
+ debugData(`Features (a: ${labelA}): ${JSON.stringify(featuresA)}`);
92
+ debugData(`Features (b: ${labelB}): ${JSON.stringify(featuresB)}`);
93
+ const featurePairs = generateFeaturePairs(featuresA, featuresB);
94
+ const similarityVector = generateSimilarityVector(featurePairs);
95
+ if (similarityVector.some(v => v >= minProbabilityQuantifier)) {
96
+ const probability = calculateProbability(similarityVector);
97
+ debug(`probability: ${probability} (Treshold: ${treshold})`);
98
+ return returnResult({
99
+ match: probability >= treshold,
100
+ probability
101
+ });
102
+ }
103
+ debugData(`No feature yielded minimum probability amount of points (${minProbabilityQuantifier})`);
104
+ return returnResult({
105
+ match: false,
106
+ probability: 0.0
107
+ });
82
108
  }
83
-
84
- function extractFeatures(record) {
109
+ function extractFeatures({
110
+ record,
111
+ recordExternal
112
+ }) {
85
113
  return strategy.reduce((acc, {
86
114
  name,
87
115
  extract
88
116
  }) => acc.concat({
89
117
  name,
90
- value: extract(record)
118
+ value: extract({
119
+ record,
120
+ recordExternal
121
+ })
91
122
  }), []);
92
123
  }
93
-
94
- function generateSimilarityVector() {
124
+ function returnResult(result) {
125
+ if (returnStrategy) {
126
+ debug(`Returning detection strategy with the result`);
127
+ const resultWithStrategy = {
128
+ match: result.match,
129
+ probability: result.probability,
130
+ strategy: formatStrategy(strategy),
131
+ treshold
132
+ };
133
+ debugData(`${JSON.stringify(resultWithStrategy)}`);
134
+ return resultWithStrategy;
135
+ }
136
+ return result;
137
+ }
138
+ function formatStrategy(strategy) {
139
+ const strategyNames = strategy.map(element => element.name);
140
+ return strategyNames || [];
141
+ }
142
+ function calculateProbability(similarityVector) {
143
+ const probability = similarityVector.reduce((acc, v) => acc + v, 0.0);
144
+ return probability > 1.0 ? 1.0 : probability;
145
+ }
146
+ function generateSimilarityVector(featurePairs) {
95
147
  const compared = featurePairs.map(({
96
148
  name,
97
149
  a,
@@ -113,13 +165,11 @@ var _default = ({
113
165
  points
114
166
  }) => points);
115
167
  }
116
-
117
- function generateFeaturePairs() {
168
+ function generateFeaturePairs(featuresA, featuresB) {
118
169
  const pairs = generatePairs();
119
170
  const missingFeatures = findMissing();
120
171
  debug(`Not comparing the following features because one, or both records are missing features: ${JSON.stringify(missingFeatures)}`);
121
172
  return pairs;
122
-
123
173
  function generatePairs() {
124
174
  return featuresA.reduce((acc, {
125
175
  name,
@@ -135,11 +185,9 @@ var _default = ({
135
185
  if (a.length === 0 || b.length === 0) {
136
186
  return false;
137
187
  }
138
-
139
188
  return true;
140
189
  });
141
190
  }
142
-
143
191
  function findMissing() {
144
192
  return featuresA.map(({
145
193
  name
@@ -149,6 +197,5 @@ var _default = ({
149
197
  }
150
198
  }
151
199
  };
152
-
153
200
  exports.default = _default;
154
201
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/match-detection/index.js"],"names":["strategy","treshold","recordA","recordB","minProbabilityQuantifier","debug","debugData","extend","featuresA","extractFeatures","featuresB","JSON","stringify","featurePairs","generateFeaturePairs","similarityVector","generateSimilarityVector","some","v","probability","calculateprobability","match","reduce","acc","record","name","extract","concat","value","compared","map","a","b","compare","find","featureName","points","pairs","generatePairs","missingFeatures","findMissing","index","filter","length"],"mappings":"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","sourcesContent":["/* eslint-disable no-console */\n/**\n*\n* @licstart The following is the entire license notice for the JavaScript code in this file.\n*\n* Melinda record matching modules for Javascript\n*\n* Copyright (C) 2020 University Of Helsinki (The National Library Of Finland)\n*\n* This file is part of melinda-record-matching-js\n*\n* melinda-record-matching-js program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Lesser General Public License as\n* published by the Free Software Foundation, either version 3 of the\n* License, or (at your option) any later version.\n*\n* melinda-record-matching-js is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n* GNU Lesser General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. If not, see <http://www.gnu.org/licenses/>.\n*\n* @licend The above is the entire license notice\n* for the JavaScript code in this file.\n*\n*/\n\nimport createDebugLogger from 'debug';\nimport * as features from './features';\n\nexport {features};\n\n// eslint-disable-next-line max-statements\nexport default ({strategy, treshold = 0.9}) => (recordA, recordB) => {\n const minProbabilityQuantifier = 0.5;\n\n const debug = createDebugLogger('@natlibfi/melinda-record-matching:match-detection');\n const debugData = debug.extend('data');\n const featuresA = extractFeatures(recordA);\n const featuresB = extractFeatures(recordB);\n\n debugData(`Features (a): ${JSON.stringify(featuresA)}`);\n debugData(`Features (b): ${JSON.stringify(featuresB)}`);\n\n const featurePairs = generateFeaturePairs();\n const similarityVector = generateSimilarityVector();\n\n if (similarityVector.some(v => v >= minProbabilityQuantifier)) {\n const probability = calculateprobability();\n debug(`probability: ${probability} (Treshold: ${treshold})`);\n return {match: probability >= treshold, probability};\n }\n\n debugData(`No feature yielded minimum probability amount of points (${minProbabilityQuantifier})`);\n return {match: false, probability: 0.0};\n\n function calculateprobability() {\n const probability = similarityVector.reduce((acc, v) => acc + v, 0.0);\n return probability > 1.0 ? 1.0 : probability;\n }\n\n function extractFeatures(record) {\n return strategy.reduce((acc, {name, extract}) => acc.concat({name, value: extract(record)}), []);\n }\n\n function generateSimilarityVector() {\n const compared = featurePairs.map(({name, a, b}) => {\n const {compare} = strategy.find(({name: featureName}) => name === featureName);\n const points = compare(a, b);\n return {name, points};\n });\n\n debugData(`Points: ${JSON.stringify(compared)}`);\n return compared.map(({points}) => points);\n }\n\n function generateFeaturePairs() {\n const pairs = generatePairs();\n const missingFeatures = findMissing();\n\n debug(`Not comparing the following features because one, or both records are missing features: ${JSON.stringify(missingFeatures)}`);\n return pairs;\n\n function generatePairs() {\n return featuresA\n .reduce((acc, {name, value}, index) => acc.concat({\n name,\n a: value,\n b: featuresB[index].value\n }), [])\n .filter(({a, b}) => {\n if (a.length === 0 || b.length === 0) {\n return false;\n }\n\n return true;\n });\n }\n\n function findMissing() {\n return featuresA\n .map(({name}) => name)\n .filter(v => pairs.some(({name}) => name === v) === false);\n }\n }\n};\n"],"file":"index.js"}
1
+ {"version":3,"file":"index.js","names":["_debug","_interopRequireDefault","require","features","_interopRequireWildcard","exports","_getRequireWildcardCache","nodeInterop","WeakMap","cacheBabelInterop","cacheNodeInterop","obj","__esModule","default","cache","has","get","newObj","hasPropertyDescriptor","Object","defineProperty","getOwnPropertyDescriptor","key","prototype","hasOwnProperty","call","desc","set","_default","strategy","treshold","returnStrategy","localSettings","recordA","recordB","recordAExternal","recordBExternal","minProbabilityQuantifier","debug","createDebugLogger","debugData","extend","JSON","stringify","featuresA","extractFeatures","record","recordExternal","Array","isArray","recordsB","recordsBExternal","detectionResults","map","index","actualDetection","labelA","label","labelB","featuresB","featurePairs","generateFeaturePairs","similarityVector","generateSimilarityVector","some","v","probability","calculateProbability","returnResult","match","reduce","acc","name","extract","concat","value","result","resultWithStrategy","formatStrategy","strategyNames","element","compared","a","b","compare","find","featureName","points","pairs","generatePairs","missingFeatures","findMissing","filter","length"],"sources":["../../src/match-detection/index.js"],"sourcesContent":["/**\n*\n* @licstart The following is the entire license notice for the JavaScript code in this file.\n*\n* Melinda record matching modules for Javascript\n*\n* Copyright (C) 2020 University Of Helsinki (The National Library Of Finland)\n*\n* This file is part of melinda-record-matching-js\n*\n* melinda-record-matching-js program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Lesser General Public License as\n* published by the Free Software Foundation, either version 3 of the\n* License, or (at your option) any later version.\n*\n* melinda-record-matching-js is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n* GNU Lesser General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. If not, see <http://www.gnu.org/licenses/>.\n*\n* @licend The above is the entire license notice\n* for the JavaScript code in this file.\n*\n*/\n\nimport createDebugLogger from 'debug';\nimport * as features from './features';\n\nexport {features};\n\nexport default ({strategy, treshold = 0.9}, returnStrategy = false, localSettings = {}) => ({recordA, recordB, recordAExternal = {}, recordBExternal = {}}) => {\n const minProbabilityQuantifier = 0.5;\n\n const debug = createDebugLogger('@natlibfi/melinda-record-matching:match-detection');\n const debugData = debug.extend('data');\n\n debugData(`Strategy: ${JSON.stringify(strategy)}, Treshold: ${JSON.stringify(treshold)}, ReturnStrategy: ${JSON.stringify(returnStrategy)}`);\n debugData(`Records: A: ${recordA}\\nB: ${recordB}`);\n debug(`Externals: A: ${JSON.stringify(recordAExternal)}, B: ${JSON.stringify(recordBExternal)}`);\n // We could add here labels for records if we didn't get external labels\n\n const featuresA = extractFeatures({record: recordA, recordExternal: recordAExternal, localSettings});\n\n debug(`We got an array of records: ${Array.isArray(recordB)}`);\n const recordsB = Array.isArray(recordB) ? recordB : [recordB];\n const recordsBExternal = Array.isArray(recordB) ? recordBExternal : [recordBExternal];\n\n const detectionResults = recordsB.map((record, index) => actualDetection({featuresA, recordAExternal, record, recordExternal: recordsBExternal[index], index}));\n\n // if we got array of records, we return an array of result\n // if we got a singular record, we return a singular result\n return Array.isArray(recordB) ? detectionResults : detectionResults[0];\n\n function actualDetection({featuresA, record, recordExternal, index, localSettings}) {\n const labelA = recordAExternal && recordAExternal.label ? recordAExternal.label : 'a';\n const labelB = recordExternal && recordExternal.label ? recordExternal.label : 'b';\n\n\n debug(`Actual detection for record ${index + 1} ${labelB}`);\n const featuresB = extractFeatures({record, recordExternal, localSettings});\n\n debugData(`Features (a: ${labelA}): ${JSON.stringify(featuresA)}`);\n debugData(`Features (b: ${labelB}): ${JSON.stringify(featuresB)}`);\n\n const featurePairs = generateFeaturePairs(featuresA, featuresB);\n const similarityVector = generateSimilarityVector(featurePairs);\n\n if (similarityVector.some(v => v >= minProbabilityQuantifier)) {\n const probability = calculateProbability(similarityVector);\n debug(`probability: ${probability} (Treshold: ${treshold})`);\n return returnResult({match: probability >= treshold, probability});\n }\n\n debugData(`No feature yielded minimum probability amount of points (${minProbabilityQuantifier})`);\n return returnResult({match: false, probability: 0.0});\n }\n\n function extractFeatures({record, recordExternal}) {\n return strategy.reduce((acc, {name, extract}) => acc.concat({name, value: extract({record, recordExternal})}), []);\n }\n\n function returnResult(result) {\n if (returnStrategy) {\n debug(`Returning detection strategy with the result`);\n const resultWithStrategy = {match: result.match, probability: result.probability, strategy: formatStrategy(strategy), treshold};\n debugData(`${JSON.stringify(resultWithStrategy)}`);\n return resultWithStrategy;\n }\n return result;\n }\n\n function formatStrategy(strategy) {\n const strategyNames = strategy.map(element => element.name);\n return strategyNames || [];\n }\n\n function calculateProbability(similarityVector) {\n const probability = similarityVector.reduce((acc, v) => acc + v, 0.0);\n return probability > 1.0 ? 1.0 : probability;\n }\n\n function generateSimilarityVector(featurePairs) {\n const compared = featurePairs.map(({name, a, b}) => {\n const {compare} = strategy.find(({name: featureName}) => name === featureName);\n const points = compare(a, b);\n return {name, points};\n });\n\n debugData(`Points: ${JSON.stringify(compared)}`);\n return compared.map(({points}) => points);\n }\n\n function generateFeaturePairs(featuresA, featuresB) {\n const pairs = generatePairs();\n const missingFeatures = findMissing();\n\n debug(`Not comparing the following features because one, or both records are missing features: ${JSON.stringify(missingFeatures)}`);\n return pairs;\n\n function generatePairs() {\n return featuresA\n .reduce((acc, {name, value}, index) => acc.concat({\n name,\n a: value,\n b: featuresB[index].value\n }), [])\n .filter(({a, b}) => {\n if (a.length === 0 || b.length === 0) {\n return false;\n }\n\n return true;\n });\n }\n\n function findMissing() {\n return featuresA\n .map(({name}) => name)\n .filter(v => pairs.some(({name}) => name === v) === false);\n }\n }\n\n};\n"],"mappings":"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"}
@@ -1,23 +1,16 @@
1
1
  "use strict";
2
2
 
3
3
  var _fixugen = _interopRequireDefault(require("@natlibfi/fixugen"));
4
-
5
4
  var _fixura = require("@natlibfi/fixura");
6
-
7
5
  var _chai = require("chai");
8
-
9
6
  var _marcRecord = require("@natlibfi/marc-record");
10
-
11
7
  var features = _interopRequireWildcard(require("./features"));
12
-
13
8
  var _ = _interopRequireDefault(require("."));
14
-
9
+ var _util = require("util");
10
+ var _debug = _interopRequireDefault(require("debug"));
15
11
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
16
-
17
12
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
18
-
19
13
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20
-
21
14
  /**
22
15
  *
23
16
  * @licstart The following is the entire license notice for the JavaScript code in this file.
@@ -45,6 +38,9 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
45
38
  * for the JavaScript code in this file.
46
39
  *
47
40
  */
41
+
42
+ const debug = (0, _debug.default)('@natlibfi/melinda-record-matching:match-detection:test');
43
+ const debugData = debug.extend('data');
48
44
  describe('match-detection', () => {
49
45
  (0, _fixugen.default)({
50
46
  path: [__dirname, '..', '..', 'test-fixtures', 'match-detection', 'index'],
@@ -57,21 +53,35 @@ describe('match-detection', () => {
57
53
  getFixture,
58
54
  options,
59
55
  expectedResults,
56
+ array,
60
57
  enabled = true
61
58
  }) => {
62
59
  if (!enabled) {
60
+ debug(`*** DISABLED TEST! ***`);
63
61
  return;
64
62
  }
65
-
66
63
  const detect = (0, _.default)(formatOptions());
67
- const recordA = new _marcRecord.MarcRecord(getFixture('recordA.json'));
68
- const recordB = new _marcRecord.MarcRecord(getFixture('recordB.json'));
69
- const results = detect(recordA, recordB);
64
+ const recordA = new _marcRecord.MarcRecord(getFixture('recordA.json'), {
65
+ subfieldValues: false
66
+ });
67
+ debugData((0, _util.inspect)(recordA));
68
+ debug(`Our recordB is an array of records: ${array}`);
69
+ const recordB = array ? getFixture('recordB.json').map(recordJson => new _marcRecord.MarcRecord(recordJson, {
70
+ subfieldValues: false
71
+ })) : new _marcRecord.MarcRecord(getFixture('recordB.json'), {
72
+ subfieldValues: false
73
+ });
74
+ debugData((0, _util.inspect)(recordB));
75
+ const results = detect({
76
+ recordA,
77
+ recordB
78
+ });
79
+ debugData(`${JSON.stringify(results)}`);
70
80
  (0, _chai.expect)(results).to.eql(expectedResults);
71
-
72
81
  function formatOptions() {
73
82
  const contextFeatures = features[options.strategy.type];
74
- return { ...options,
83
+ return {
84
+ ...options,
75
85
  strategy: options.strategy.features.map(v => contextFeatures[v]())
76
86
  };
77
87
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/match-detection/index.spec.js"],"names":["describe","path","__dirname","useMetadataFile","recurse","fixura","reader","READERS","JSON","callback","getFixture","options","expectedResults","enabled","detect","formatOptions","recordA","MarcRecord","recordB","results","to","eql","contextFeatures","features","strategy","type","map","v"],"mappings":";;AA4BA;;AACA;;AACA;;AACA;;AACA;;AACA;;;;;;;;AAjCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AASAA,QAAQ,CAAC,iBAAD,EAAoB,MAAM;AAChC,wBAAc;AACZC,IAAAA,IAAI,EAAE,CAACC,SAAD,EAAY,IAAZ,EAAkB,IAAlB,EAAwB,eAAxB,EAAyC,iBAAzC,EAA4D,OAA5D,CADM;AAEZC,IAAAA,eAAe,EAAE,IAFL;AAGZC,IAAAA,OAAO,EAAE,KAHG;AAIZC,IAAAA,MAAM,EAAE;AACNC,MAAAA,MAAM,EAAEC,gBAAQC;AADV,KAJI;AAOZC,IAAAA,QAAQ,EAAE,CAAC;AAACC,MAAAA,UAAD;AAAaC,MAAAA,OAAb;AAAsBC,MAAAA,eAAtB;AAAuCC,MAAAA,OAAO,GAAG;AAAjD,KAAD,KAA4D;AAEpE,UAAI,CAACA,OAAL,EAAc;AACZ;AACD;;AAED,YAAMC,MAAM,GAAG,eAAyBC,aAAa,EAAtC,CAAf;AACA,YAAMC,OAAO,GAAG,IAAIC,sBAAJ,CAAeP,UAAU,CAAC,cAAD,CAAzB,CAAhB;AACA,YAAMQ,OAAO,GAAG,IAAID,sBAAJ,CAAeP,UAAU,CAAC,cAAD,CAAzB,CAAhB;AACA,YAAMS,OAAO,GAAGL,MAAM,CAACE,OAAD,EAAUE,OAAV,CAAtB;AAEA,wBAAOC,OAAP,EAAgBC,EAAhB,CAAmBC,GAAnB,CAAuBT,eAAvB;;AAEA,eAASG,aAAT,GAAyB;AACvB,cAAMO,eAAe,GAAGC,QAAQ,CAACZ,OAAO,CAACa,QAAR,CAAiBC,IAAlB,CAAhC;AAEA,eAAO,EACL,GAAGd,OADE;AAELa,UAAAA,QAAQ,EAAEb,OAAO,CAACa,QAAR,CAAiBD,QAAjB,CAA0BG,GAA1B,CAA8BC,CAAC,IAAIL,eAAe,CAACK,CAAD,CAAf,EAAnC;AAFL,SAAP;AAID;AACF;AA5BW,GAAd;AA8BD,CA/BO,CAAR","sourcesContent":["/**\n*\n* @licstart The following is the entire license notice for the JavaScript code in this file.\n*\n* Melinda record matching modules for Javascript\n*\n* Copyright (C) 2020 University Of Helsinki (The National Library Of Finland)\n*\n* This file is part of melinda-record-matching-js\n*\n* melinda-record-matching-js program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Lesser General Public License as\n* published by the Free Software Foundation, either version 3 of the\n* License, or (at your option) any later version.\n*\n* melinda-record-matching-js is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n* GNU Lesser General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. If not, see <http://www.gnu.org/licenses/>.\n*\n* @licend The above is the entire license notice\n* for the JavaScript code in this file.\n*\n*/\n\nimport generateTests from '@natlibfi/fixugen';\nimport {READERS} from '@natlibfi/fixura';\nimport {expect} from 'chai';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport * as features from './features';\nimport createDetectionInterface from '.';\n\ndescribe('match-detection', () => {\n generateTests({\n path: [__dirname, '..', '..', 'test-fixtures', 'match-detection', 'index'],\n useMetadataFile: true,\n recurse: false,\n fixura: {\n reader: READERS.JSON\n },\n callback: ({getFixture, options, expectedResults, enabled = true}) => {\n\n if (!enabled) {\n return;\n }\n\n const detect = createDetectionInterface(formatOptions());\n const recordA = new MarcRecord(getFixture('recordA.json'));\n const recordB = new MarcRecord(getFixture('recordB.json'));\n const results = detect(recordA, recordB);\n\n expect(results).to.eql(expectedResults);\n\n function formatOptions() {\n const contextFeatures = features[options.strategy.type];\n\n return {\n ...options,\n strategy: options.strategy.features.map(v => contextFeatures[v]())\n };\n }\n }\n });\n});\n"],"file":"index.spec.js"}
1
+ {"version":3,"file":"index.spec.js","names":["_fixugen","_interopRequireDefault","require","_fixura","_chai","_marcRecord","features","_interopRequireWildcard","_","_util","_debug","_getRequireWildcardCache","nodeInterop","WeakMap","cacheBabelInterop","cacheNodeInterop","obj","__esModule","default","cache","has","get","newObj","hasPropertyDescriptor","Object","defineProperty","getOwnPropertyDescriptor","key","prototype","hasOwnProperty","call","desc","set","debug","createDebugLogger","debugData","extend","describe","generateTests","path","__dirname","useMetadataFile","recurse","fixura","reader","READERS","JSON","callback","getFixture","options","expectedResults","array","enabled","detect","createDetectionInterface","formatOptions","recordA","MarcRecord","subfieldValues","inspect","recordB","map","recordJson","results","stringify","expect","to","eql","contextFeatures","strategy","type","v"],"sources":["../../src/match-detection/index.spec.js"],"sourcesContent":["/**\n*\n* @licstart The following is the entire license notice for the JavaScript code in this file.\n*\n* Melinda record matching modules for Javascript\n*\n* Copyright (C) 2020 University Of Helsinki (The National Library Of Finland)\n*\n* This file is part of melinda-record-matching-js\n*\n* melinda-record-matching-js program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Lesser General Public License as\n* published by the Free Software Foundation, either version 3 of the\n* License, or (at your option) any later version.\n*\n* melinda-record-matching-js is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n* GNU Lesser General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. If not, see <http://www.gnu.org/licenses/>.\n*\n* @licend The above is the entire license notice\n* for the JavaScript code in this file.\n*\n*/\n\nimport generateTests from '@natlibfi/fixugen';\nimport {READERS} from '@natlibfi/fixura';\nimport {expect} from 'chai';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport * as features from './features';\nimport createDetectionInterface from '.';\nimport {inspect} from 'util';\nimport createDebugLogger from 'debug';\n\nconst debug = createDebugLogger('@natlibfi/melinda-record-matching:match-detection:test');\nconst debugData = debug.extend('data');\n\ndescribe('match-detection', () => {\n generateTests({\n path: [__dirname, '..', '..', 'test-fixtures', 'match-detection', 'index'],\n useMetadataFile: true,\n recurse: false,\n fixura: {\n reader: READERS.JSON\n },\n callback: ({getFixture, options, expectedResults, array, enabled = true}) => {\n\n if (!enabled) {\n debug(`*** DISABLED TEST! ***`);\n return;\n }\n\n const detect = createDetectionInterface(formatOptions());\n const recordA = new MarcRecord(getFixture('recordA.json'), {subfieldValues: false});\n debugData(inspect(recordA));\n\n debug(`Our recordB is an array of records: ${array}`);\n const recordB = array\n ? getFixture('recordB.json').map(recordJson => new MarcRecord(recordJson, {subfieldValues: false}))\n : new MarcRecord(getFixture('recordB.json'), {subfieldValues: false});\n debugData(inspect(recordB));\n\n const results = detect({recordA, recordB});\n debugData(`${JSON.stringify(results)}`);\n\n expect(results).to.eql(expectedResults);\n\n function formatOptions() {\n const contextFeatures = features[options.strategy.type];\n\n return {\n ...options,\n strategy: options.strategy.features.map(v => contextFeatures[v]())\n };\n }\n }\n });\n});\n"],"mappings":";;AA4BA,IAAAA,QAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,OAAA,GAAAD,OAAA;AACA,IAAAE,KAAA,GAAAF,OAAA;AACA,IAAAG,WAAA,GAAAH,OAAA;AACA,IAAAI,QAAA,GAAAC,uBAAA,CAAAL,OAAA;AACA,IAAAM,CAAA,GAAAP,sBAAA,CAAAC,OAAA;AACA,IAAAO,KAAA,GAAAP,OAAA;AACA,IAAAQ,MAAA,GAAAT,sBAAA,CAAAC,OAAA;AAAsC,SAAAS,yBAAAC,WAAA,eAAAC,OAAA,kCAAAC,iBAAA,OAAAD,OAAA,QAAAE,gBAAA,OAAAF,OAAA,YAAAF,wBAAA,YAAAA,CAAAC,WAAA,WAAAA,WAAA,GAAAG,gBAAA,GAAAD,iBAAA,KAAAF,WAAA;AAAA,SAAAL,wBAAAS,GAAA,EAAAJ,WAAA,SAAAA,WAAA,IAAAI,GAAA,IAAAA,GAAA,CAAAC,UAAA,WAAAD,GAAA,QAAAA,GAAA,oBAAAA,GAAA,wBAAAA,GAAA,4BAAAE,OAAA,EAAAF,GAAA,UAAAG,KAAA,GAAAR,wBAAA,CAAAC,WAAA,OAAAO,KAAA,IAAAA,KAAA,CAAAC,GAAA,CAAAJ,GAAA,YAAAG,KAAA,CAAAE,GAAA,CAAAL,GAAA,SAAAM,MAAA,WAAAC,qBAAA,GAAAC,MAAA,CAAAC,cAAA,IAAAD,MAAA,CAAAE,wBAAA,WAAAC,GAAA,IAAAX,GAAA,QAAAW,GAAA,kBAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAd,GAAA,EAAAW,GAAA,SAAAI,IAAA,GAAAR,qBAAA,GAAAC,MAAA,CAAAE,wBAAA,CAAAV,GAAA,EAAAW,GAAA,cAAAI,IAAA,KAAAA,IAAA,CAAAV,GAAA,IAAAU,IAAA,CAAAC,GAAA,KAAAR,MAAA,CAAAC,cAAA,CAAAH,MAAA,EAAAK,GAAA,EAAAI,IAAA,YAAAT,MAAA,CAAAK,GAAA,IAAAX,GAAA,CAAAW,GAAA,SAAAL,MAAA,CAAAJ,OAAA,GAAAF,GAAA,MAAAG,KAAA,IAAAA,KAAA,CAAAa,GAAA,CAAAhB,GAAA,EAAAM,MAAA,YAAAA,MAAA;AAAA,SAAArB,uBAAAe,GAAA,WAAAA,GAAA,IAAAA,GAAA,CAAAC,UAAA,GAAAD,GAAA,KAAAE,OAAA,EAAAF,GAAA;AAnCtC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAWA,MAAMiB,KAAK,GAAG,IAAAC,cAAiB,EAAC,wDAAwD,CAAC;AACzF,MAAMC,SAAS,GAAGF,KAAK,CAACG,MAAM,CAAC,MAAM,CAAC;AAEtCC,QAAQ,CAAC,iBAAiB,EAAE,MAAM;EAChC,IAAAC,gBAAa,EAAC;IACZC,IAAI,EAAE,CAACC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,eAAe,EAAE,iBAAiB,EAAE,OAAO,CAAC;IAC1EC,eAAe,EAAE,IAAI;IACrBC,OAAO,EAAE,KAAK;IACdC,MAAM,EAAE;MACNC,MAAM,EAAEC,eAAO,CAACC;IAClB,CAAC;IACDC,QAAQ,EAAEA,CAAC;MAACC,UAAU;MAAEC,OAAO;MAAEC,eAAe;MAAEC,KAAK;MAAEC,OAAO,GAAG;IAAI,CAAC,KAAK;MAE3E,IAAI,CAACA,OAAO,EAAE;QACZnB,KAAK,CAAE,wBAAuB,CAAC;QAC/B;MACF;MAEA,MAAMoB,MAAM,GAAG,IAAAC,SAAwB,EAACC,aAAa,CAAC,CAAC,CAAC;MACxD,MAAMC,OAAO,GAAG,IAAIC,sBAAU,CAACT,UAAU,CAAC,cAAc,CAAC,EAAE;QAACU,cAAc,EAAE;MAAK,CAAC,CAAC;MACnFvB,SAAS,CAAC,IAAAwB,aAAO,EAACH,OAAO,CAAC,CAAC;MAE3BvB,KAAK,CAAE,uCAAsCkB,KAAM,EAAC,CAAC;MACrD,MAAMS,OAAO,GAAGT,KAAK,GACjBH,UAAU,CAAC,cAAc,CAAC,CAACa,GAAG,CAACC,UAAU,IAAI,IAAIL,sBAAU,CAACK,UAAU,EAAE;QAACJ,cAAc,EAAE;MAAK,CAAC,CAAC,CAAC,GACjG,IAAID,sBAAU,CAACT,UAAU,CAAC,cAAc,CAAC,EAAE;QAACU,cAAc,EAAE;MAAK,CAAC,CAAC;MACvEvB,SAAS,CAAC,IAAAwB,aAAO,EAACC,OAAO,CAAC,CAAC;MAE3B,MAAMG,OAAO,GAAGV,MAAM,CAAC;QAACG,OAAO;QAAEI;MAAO,CAAC,CAAC;MAC1CzB,SAAS,CAAE,GAAEW,IAAI,CAACkB,SAAS,CAACD,OAAO,CAAE,EAAC,CAAC;MAEvC,IAAAE,YAAM,EAACF,OAAO,CAAC,CAACG,EAAE,CAACC,GAAG,CAACjB,eAAe,CAAC;MAEvC,SAASK,aAAaA,CAAA,EAAG;QACvB,MAAMa,eAAe,GAAG9D,QAAQ,CAAC2C,OAAO,CAACoB,QAAQ,CAACC,IAAI,CAAC;QAEvD,OAAO;UACL,GAAGrB,OAAO;UACVoB,QAAQ,EAAEpB,OAAO,CAACoB,QAAQ,CAAC/D,QAAQ,CAACuD,GAAG,CAACU,CAAC,IAAIH,eAAe,CAACG,CAAC,CAAC,CAAC,CAAC;QACnE,CAAC;MACH;IACF;EACF,CAAC,CAAC;AACJ,CAAC,CAAC"}