@natlibfi/melinda-record-matching 2.2.0-alpha.2 → 2.2.0-alpha.3

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/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.js"],"names":["detection","detectionOptions","search","searchOptions","maxMatches","maxCandidates","returnStrategy","returnQuery","returnNonMatches","returnFailures","debug","debugData","extend","JSON","stringify","detect","record","iterate","initialState","matches","candidateCount","nonMatches","duplicateCount","nonMatchCount","conversionFailures","records","failures","state","length","recordSetSize","failureSetSize","newCandidateCount","newConversionFailures","concat","handleRecordSet","queriesLeft","searchCounter","query","returnResult","stopReason","matchResult","iterateRecords","newDuplicateCount","newNonMatchCount","newMatches","newNonMatches","handleMatchResult","maxMatchesFound","maxCandidatesRetrieved","addQuery","map","match","matchQuery","conversionFailureCount","checkCounts","matchStatus","getMatchState","matchesResult","result","matchCount","chosenNonMatchCount","totalHandled","conversionFailuresCount","resultSetOffset","totalRecords","queryCandidateCounter","maxedQueries","searchesLeft","nonRetrieved","maxedQueriesStopReason","undefined","conversionFailuresStopReason","newStopReason","status","recordMatches","recordNonMatches","recordCount","recordDuplicateCount","recordNonMatchCount","candidate","newRecordCount","candidateNotInMatches","candidateRecord","id","candidateId","detectionResult","handleDetectionResult","slice","strategy","treshold","probability","strategyResult","newMatch","handleRecordMatch","newRecordNonMatchCount","isMatch","newRecordMatches","newRecordNonMatches","newCandidateId","find"],"mappings":"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","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\nimport createDebugLogger from 'debug';\nimport createSearchInterface, * as candidateSearch from './candidate-search';\nimport createDetectionInterface, * as matchDetection from './match-detection';\n\nexport {candidateSearch, matchDetection};\n\nexport default ({detection: detectionOptions, search: searchOptions, maxMatches = 1, maxCandidates = 25, returnStrategy = false, returnQuery = false, returnNonMatches = false, returnFailures = false}) => {\n const debug = createDebugLogger('@natlibfi/melinda-record-matching:index');\n const debugData = debug.extend('data');\n\n debugData(`DetectionOptions: ${JSON.stringify(detectionOptions)}`);\n debugData(`SearchOptions: ${JSON.stringify(searchOptions)}`);\n debugData(`MaxMatches: ${JSON.stringify(maxMatches)}`);\n debugData(`MaxCandidates: ${JSON.stringify(maxCandidates)}`);\n debugData(`ReturnStrategy: ${JSON.stringify(returnStrategy)}`);\n debugData(`ReturnQuery: ${JSON.stringify(returnQuery)}`);\n debugData(`ReturnNonMatches: ${JSON.stringify(returnNonMatches)}`);\n debugData(`ReturnFailures: ${JSON.stringify(returnFailures)}`);\n\n\n const detect = createDetectionInterface(detectionOptions, returnStrategy);\n\n return record => {\n const search = createSearchInterface({...searchOptions, record, maxCandidates});\n return iterate({});\n\n // candidateCount : amount of candidate records retrived from SRU for matching, NOT including current record set\n // matches : candidates that have been detected as matches by current matcher job\n // nonMatches : candidates that have been detected as non-matches by current matcher job (only if returnNonMatches is 'true')\n // duplicateCount : amount of candidate records that were retrieved from the SRU but not handled further because they were already found in the matches/nonMatches\n\n // state.totalRecords : amount of candidate records available to the current query (undefined, if there was no queries left)\n // state.query : current query (undefined if there was no queries left)\n // state.searchCounter : sequence for current search for current query (undefined, if there we no queries left)\n // state.queryCandidateCounter: amount of candidate records retrieved from SRU for matching for current query, including the current record set (undefined if there were no queries left)\n // state.queriesLeft : amount of queries left\n // state.queryCounter : sequence for current query\n // state.maxedQueries : queries that resulted in more than serverMaxResults hits\n\n async function iterate({initialState = {}, matches = [], candidateCount = 0, nonMatches = [], duplicateCount = 0, nonMatchCount = 0, conversionFailures = []}) {\n debugData(`Starting next matcher iteration.`);\n const {records, failures, ...state} = await search(initialState);\n\n debugData(`Current state: ${JSON.stringify(state)}, matches: ${matches.length}, candidateCount: ${candidateCount}, nonMatches: ${nonMatches.length}, nonMatchCount: ${nonMatchCount}, conversionFailures: ${conversionFailures}`);\n const recordSetSize = records.length;\n const failureSetSize = failures.length;\n const newCandidateCount = candidateCount + recordSetSize + failureSetSize;\n\n const newConversionFailures = conversionFailures.concat(failures);\n debugData(`Failures: ${failures.length}, ConversionFailures: ${conversionFailures.length}, NewConversionFailures: ${newConversionFailures.length}`);\n\n if (recordSetSize > 0) {\n return handleRecordSet();\n }\n\n if (state.queriesLeft > 0) {\n debug(`Empty record set ${state.searchCounter} for ${state.query}, but there are ${state.queriesLeft} queries left`);\n return iterate({initialState: state, matches, candidateCount: newCandidateCount, nonMatches, nonMatchCount, duplicateCount, conversionFailures: newConversionFailures});\n }\n\n debug(`No (more) candidate records to check, no more queries left, matches: ${matches.length}`);\n return returnResult({matches, state, stopReason: '', nonMatches, nonMatchCount, candidateCount: newCandidateCount, duplicateCount, conversionFailures: newConversionFailures});\n\n function handleRecordSet() {\n debug(`Checking record set of ${recordSetSize} candidate records for possible matches, found by ${state.searchCounter} search for ${state.query}`);\n\n const matchResult = iterateRecords({records, recordSetSize, maxMatches, matches, nonMatches, nonMatchCount});\n\n const newDuplicateCount = duplicateCount + matchResult.duplicateCount;\n const newNonMatchCount = nonMatchCount + matchResult.nonMatchCount;\n const {newMatches, newNonMatches} = handleMatchResult(matchResult, matches, nonMatches);\n\n if (maxMatchesFound({matches: newMatches, maxMatches})) {\n return returnResult({matches: newMatches, state, stopReason: 'maxMatches', nonMatches: newNonMatches, duplicateCount: newDuplicateCount, candidateCount: newCandidateCount, nonMatchCount: newNonMatchCount, conversionFailures: newConversionFailures});\n }\n\n if (maxCandidatesRetrieved(newCandidateCount, maxCandidates)) {\n return returnResult({matches: newMatches, state, stopReason: 'maxCandidates', nonMatches: newNonMatches, duplicateCount: newDuplicateCount, candidateCount: newCandidateCount, nonMatchCount: newNonMatchCount, conversionFailures: newConversionFailures});\n }\n\n return iterate({initialState: state, matches: newMatches, candidateCount: newCandidateCount, nonMatches: newNonMatches, duplicateCount: newDuplicateCount, nonMatchCount: newNonMatchCount, conversionFailures: newConversionFailures});\n }\n\n function handleMatchResult(matchResult, matches, nonMatches) {\n debugData(`- Amount of new matches from record set: ${matchResult.matches.length}`);\n // eslint-disable-next-line functional/no-conditional-statement\n if (returnNonMatches) {\n debugData(`- Amount of new nonMatches from record set: ${matchResult.nonMatches.length}`);\n }\n\n const newMatches = matches.concat(returnQuery ? addQuery(matchResult.matches) : matchResult.matches);\n const newNonMatches = returnNonMatches ? nonMatches.concat(returnQuery ? addQuery(matchResult.nonMatches) : matchResult.nonMatches) : [];\n\n debugData(`- Total amount of matches: ${newMatches.length}`);\n // eslint-disable-next-line functional/no-conditional-statement\n if (returnNonMatches) {\n debugData(`- Total amount of nonMatches: ${newNonMatches.length}`);\n }\n\n return {newMatches, newNonMatches};\n }\n\n function addQuery(matches) {\n debugData(`Adding query ${state.query} to matches`);\n return matches.map((match) => ({...match, matchQuery: state.query}));\n }\n\n function maxCandidatesRetrieved(candidateCount, maxCandidates) {\n debugData(`Total amount of candidate records retrieved: ${newCandidateCount} (max: ${maxCandidates})`);\n if (maxCandidates && candidateCount >= maxCandidates) {\n debug(`Stopped matching because maximum number of candidate records ${candidateCount} / ${maxCandidates} have been retrieved`);\n return true;\n }\n }\n }\n\n // matches : array of matching candidate records\n // nonMatches : array of nonMatching candidate records (if returnNonMatches option is true, otherwise empty array)\n // - candidate.id\n // - candidate.record\n // - probability\n // - strategy (if returnStrategy option is true)\n // - treshold (if returnStrategy option is true)\n // - matchQuery (if returnQuery option is true)\n\n // we could have here also returnRecords/returnMatchRecords/returnNonMatchRecord options that could be turned false for not to return actual record data\n\n // matchStatus.status: boolean, true if matcher retrieved and handled all found candidate records, false if it did not\n // matchStatus.stopReason: string ('maxMatches','maxCandidates','maxedQueries','conversionFailures', empty string/undefined), reason for stopping retrieving or handling the candidate records\n // - only one stopReason is returned (if there would be several possible stopReasons, stopReason is picked in the above order)\n // - currently stopReason can be non-empty also in cases where status is true, if matcher hit the stop reason when handling the last available candidate record\n\n function returnResult({matches, state, stopReason, nonMatches, duplicateCount, candidateCount, nonMatchCount, conversionFailures}) {\n const conversionFailureCount = conversionFailures.length;\n checkCounts({matches, nonMatches, candidateCount, duplicateCount, nonMatchCount, conversionFailureCount});\n const matchStatus = getMatchState(state, stopReason, conversionFailureCount);\n // add nonMatches to result only if returnNonMatches is 'true', otherwise nonMatches have not been gathered\n const matchesResult = returnNonMatches ? {matches, matchStatus, nonMatches} : {matches, matchStatus};\n const result = returnFailures ? {...matchesResult, conversionFailures} : matchesResult;\n debugData(`ReturnFailures ${returnFailures}`);\n debugData(`${JSON.stringify(result)}`);\n return result;\n\n // note that in cases where the matching has been stopped because of maxMatches checkCounts won't (in most cases) match\n\n function checkCounts({matches, nonMatches, candidateCount, duplicateCount, nonMatchCount, conversionFailureCount}) {\n const matchCount = matches.length;\n debugData(`Return nonMatches: ${returnNonMatches}`);\n const chosenNonMatchCount = returnNonMatches ? nonMatches.length : nonMatchCount;\n const totalHandled = matchCount + chosenNonMatchCount + duplicateCount;\n debug(`candidateCount: ${candidateCount}, matches: ${matchCount}, nonMatches: ${chosenNonMatchCount}, duplicateCount: ${duplicateCount}, conversionFailureCount: ${conversionFailureCount}`);\n debug(`We got result for ${totalHandled} / ${candidateCount} retrieved candidates`);\n if (totalHandled !== candidateCount) {\n debug(`WARNING: Missing results for ${candidateCount - totalHandled} candidates`);\n return;\n }\n return;\n }\n\n function getMatchState(state, stopReason, conversionFailuresCount) {\n debugData(`${JSON.stringify(state)}`);\n debug(`We had ${conversionFailuresCount} retrieved candidates that could not be converted.`);\n debug(`Queries left ${state.queriesLeft}, Searches for current query left: ${state.resultSetOffset && state.resultSetOffset <= state.totalRecords}, non-retrieved records: ${state.totalRecords - state.queryCandidateCounter}, maxedQueries (${state.maxedQueries.length}): ${state.maxedQueries}`);\n\n debugData(`StopReason: <${stopReason}>`);\n\n const searchesLeft = state.resultSetOffset && state.resultSetOffset <= state.totalRecords;\n const nonRetrieved = searchesLeft ? state.totalRecords - state.queryCandidateCounter : 0;\n debugData(`nonRetrieved: ${nonRetrieved}`);\n\n // matchStatus.stopReason: string ('maxMatches','maxCandidates','maxedQueries','conversionFailures', empty string/undefined), reason for stopping retrieving or handling the candidate records\n // 'maxMatches' and 'maxCandidates' are in stopReason, 'maxedQueries' and 'conversionFailures' are created here\n\n if (state.queriesLeft > 0 || nonRetrieved > 0 || state.maxedQueries.length > 0 || conversionFailureCount > 0) {\n const maxedQueriesStopReason = state.maxedQueries.length > 0 ? 'maxedQueries' : undefined;\n const conversionFailuresStopReason = conversionFailureCount > 0 ? 'conversionFailures' : undefined;\n const newStopReason = stopReason === '' || stopReason === undefined ? maxedQueriesStopReason || conversionFailuresStopReason : stopReason;\n debugData(`MaxedQueriesStopReason: <${maxedQueriesStopReason}>`);\n debugData(`ConversionFailureStopReason <${conversionFailuresStopReason}>`);\n debugData(`NewStopReason: <${newStopReason}>`);\n debug(`Match status: false`);\n return {status: false, stopReason: newStopReason};\n }\n\n debug(`Match status: true`);\n return {status: true, stopReason};\n }\n }\n\n function iterateRecords({records, recordSetSize, maxMatches, matches = [], nonMatches = [], recordMatches = [], recordNonMatches = [], recordCount = 0, recordDuplicateCount = 0, recordNonMatchCount = 0}) {\n\n // recordSetSize : total amount of records in the current record set\n // recordCount : amount of records from the current record set that have been handled\n // maxMatches : setting for maximum amount found by current matcher job before the matcher job is stopped\n // recordDuplicateCount : amount of records from the current record set that are already included in matches/nonMatches results\n // recordNonMatchCount: amount of records from the current record set that are nonMatches (only is returnNonMatches setting is false)\n\n // records : non-handled records in the current record set\n // matches : found matches in the current matcher job\n // recordMatches : found matches in the current record set\n // recordNonMatches : found nonMatches in the current record set (only if returnNonMatches setting is true)\n\n const [candidate] = records;\n const newRecordCount = candidate ? recordCount + 1 : recordCount;\n\n // The matcher uses same matchDetection strategy for candidates from all candidate-searches -> matchDetection result for the same candidate is always same\n // Exceptions would happen if the candidate would have been updated in the database between candidate searches\n // Note that if returnNonMatches is false, matcher won't remember candidates that didn't match, so they will be matched again everytime they are retrieved by\n // different candidate search queries. Same candidate search query won't have duplicate records.\n\n if (candidate) {\n\n if (candidateNotInMatches(matches.concat(nonMatches), candidate)) {\n const {record: candidateRecord, id: candidateId} = candidate;\n debug(`Running matchDetection for record ${candidateId} (${newRecordCount}/${recordSetSize})`);\n const detectionResult = detect(record, candidateRecord);\n return handleDetectionResult(detectionResult, candidateId, candidateRecord);\n }\n return iterateRecords({records: records.slice(1), recordSetSize, maxMatches, matches, recordMatches, recordCount: newRecordCount, recordNonMatches, recordDuplicateCount: recordDuplicateCount + 1, recordNonMatchCount});\n }\n\n debug(`No more candidates, record set (${recordCount}/${recordSetSize}) done, ${recordMatches.length} matches found, ${recordDuplicateCount} candidates already handled, ${returnNonMatches ? `${recordNonMatches.length}` : `${recordNonMatchCount}`} nonMatches found.`);\n return {matches: recordMatches, nonMatches: returnNonMatches ? recordNonMatches : [], duplicateCount: recordDuplicateCount, nonMatchCount: recordNonMatchCount};\n\n function handleDetectionResult(detectionResult, candidateId, candidateRecord) {\n debugData(`MatchDetection results for ${candidateId} (${newRecordCount}/${recordSetSize}): ${JSON.stringify(detectionResult)}`);\n\n if (detectionResult.match || returnNonMatches) {\n debug(`${detectionResult.match ? `Record ${candidateId} (${newRecordCount}/${recordSetSize}) is a match!` : `Record ${candidateId} (${newRecordCount}/${recordSetSize}) is NOT a match!`}`);\n debugData(`Strategy: ${JSON.stringify(detectionResult.strategy)}, Treshold: ${JSON.stringify(detectionResult.treshold)}`);\n\n const matchResult = {\n probability: detectionResult.probability,\n candidate: {\n id: candidateId,\n record: candidateRecord\n }\n };\n const strategyResult = {\n strategy: detectionResult.strategy,\n treshold: detectionResult.treshold\n };\n const newMatch = returnStrategy ? {...matchResult, ...strategyResult} : {...matchResult};\n\n debugData(`${JSON.stringify(newMatch)}`);\n\n return handleRecordMatch(detectionResult.match, newMatch);\n }\n\n const newRecordNonMatchCount = recordNonMatchCount + 1;\n debugData(`- Total nonMatches after this detection: ${newRecordNonMatchCount}`);\n\n return iterateRecords({records: records.slice(1), recordSetSize, maxMatches, matches, recordMatches, recordCount: newRecordCount, recordNonMatches, recordDuplicateCount, recordNonMatchCount: newRecordNonMatchCount});\n }\n\n function handleRecordMatch(isMatch, newMatch) {\n const newRecordMatches = isMatch ? recordMatches.concat(newMatch) : recordMatches;\n const newRecordNonMatches = isMatch ? recordNonMatches : recordNonMatches.concat(newMatch);\n const newRecordNonMatchCount = isMatch ? recordNonMatchCount : recordNonMatchCount + 1;\n\n debugData(`- Total matches after this detection: ${matches.concat(newRecordMatches).length} (max: ${maxMatches})`);\n\n // eslint-disable-next-line functional/no-conditional-statement\n if (returnNonMatches) {\n debugData(`- Total nonMatches after this detection: ${nonMatches.concat(newRecordNonMatches).length}`);\n }\n debugData(`- Total nonMatchCount after this detection: ${recordNonMatchCount}`);\n\n if (maxMatchesFound({matches: matches.concat(newRecordMatches), maxMatches})) {\n debug(`MaxMatches (${maxMatches}) reached, handled candidates in record set: ${newRecordCount} non-handled candidates in record set ${recordSetSize - newRecordCount}`);\n return {matches: newRecordMatches, nonMatches: returnNonMatches ? newRecordNonMatches : [], duplicateCount: recordDuplicateCount, nonMatchCount: newRecordNonMatchCount};\n }\n\n return iterateRecords({records: records.slice(1), recordSetSize, maxMatches, matches, recordMatches: newRecordMatches, recordCount: newRecordCount, recordNonMatches: returnNonMatches ? newRecordNonMatches : [], duplicateCount: recordDuplicateCount, recordNonMatchCount: newRecordNonMatchCount});\n }\n\n function candidateNotInMatches(matches, candidate) {\n debug(`Checking that record ${candidate.id} is not already included in ${matches.length} matches/nonMatches`);\n const newCandidateId = candidate.id;\n debugData(`newCandidateId: ${newCandidateId}`);\n const result = matches.find(({candidate}) => candidate.id === newCandidateId);\n debugData(`Result: ${result}`);\n if (result) {\n debug(`${candidate.id} was already handled.`);\n return false;\n }\n debug(`${candidate.id} not found in matches/nonMatches`);\n return true;\n }\n }\n\n function maxMatchesFound({matches, maxMatches}) {\n if (maxMatches && matches.length >= maxMatches) {\n debug(`Stopping recordSet iteration: maxMatches (${maxMatches}) for matcher job found.`);\n return true;\n }\n }\n };\n};\n"],"file":"index.js"}
1
+ {"version":3,"sources":["../src/index.js"],"names":["detection","detectionOptions","search","searchOptions","maxMatches","maxCandidates","returnStrategy","returnQuery","returnNonMatches","returnFailures","debug","debugData","extend","JSON","stringify","detect","record","iterate","initialState","matches","candidateCount","nonMatches","duplicateCount","nonMatchCount","conversionFailures","matchErrors","records","failures","state","length","recordSetSize","failureSetSize","newCandidateCount","newConversionFailures","concat","handleRecordSet","queriesLeft","searchCounter","query","returnResult","stopReason","matchResult","iterateRecords","newDuplicateCount","newNonMatchCount","newMatches","newNonMatches","newMatchErrors","handleMatchResult","maxMatchesFound","maxCandidatesRetrieved","addQuery","map","match","matchQuery","conversionFailureCount","matchErrorCount","checkCounts","matchStatus","getMatchState","matchesResult","result","matchCount","chosenNonMatchCount","totalHandled","conversionFailuresCount","resultSetOffset","totalRecords","queryCandidateCounter","maxedQueries","searchesLeft","nonRetrieved","maxedQueriesStopReason","undefined","conversionFailuresStopReason","matchErrorsStopReason","newStopReason","status","recordMatches","recordNonMatches","recordCount","recordDuplicateCount","recordNonMatchCount","recordMatchErrors","candidate","newRecordCount","candidateNotInMatches","candidateRecord","id","candidateId","detectionResult","handleDetectionResult","error","matchError","payload","message","newRecordMatchErrors","slice","strategy","treshold","probability","strategyResult","newMatch","handleRecordMatch","newRecordNonMatchCount","isMatch","newRecordMatches","newRecordNonMatches","newCandidateId","find"],"mappings":"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","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\nimport createDebugLogger from 'debug';\nimport createSearchInterface, * as candidateSearch from './candidate-search';\nimport createDetectionInterface, * as matchDetection from './match-detection';\n//import inspect from 'util';\n\nexport {candidateSearch, matchDetection};\n\nexport default ({detection: detectionOptions, search: searchOptions, maxMatches = 1, maxCandidates = 25, returnStrategy = false, returnQuery = false, returnNonMatches = false, returnFailures = false}) => {\n const debug = createDebugLogger('@natlibfi/melinda-record-matching:index');\n const debugData = debug.extend('data');\n\n debugData(`DetectionOptions: ${JSON.stringify(detectionOptions)}`);\n debugData(`SearchOptions: ${JSON.stringify(searchOptions)}`);\n debugData(`MaxMatches: ${JSON.stringify(maxMatches)}`);\n debugData(`MaxCandidates: ${JSON.stringify(maxCandidates)}`);\n debugData(`ReturnStrategy: ${JSON.stringify(returnStrategy)}`);\n debugData(`ReturnQuery: ${JSON.stringify(returnQuery)}`);\n debugData(`ReturnNonMatches: ${JSON.stringify(returnNonMatches)}`);\n debugData(`ReturnFailures: ${JSON.stringify(returnFailures)}`);\n\n\n const detect = createDetectionInterface(detectionOptions, returnStrategy);\n\n return record => {\n const search = createSearchInterface({...searchOptions, record, maxCandidates});\n return iterate({});\n\n // candidateCount : amount of candidate records retrived from SRU for matching, NOT including current record set\n // matches : candidates that have been detected as matches by current matcher job\n // nonMatches : candidates that have been detected as non-matches by current matcher job (only if returnNonMatches is 'true')\n // duplicateCount : amount of candidate records that were retrieved from the SRU but not handled further because they were already found in the matches/nonMatches\n\n // state.totalRecords : amount of candidate records available to the current query (undefined, if there was no queries left)\n // state.query : current query (undefined if there was no queries left)\n // state.searchCounter : sequence for current search for current query (undefined, if there we no queries left)\n // state.queryCandidateCounter: amount of candidate records retrieved from SRU for matching for current query, including the current record set (undefined if there were no queries left)\n // state.queriesLeft : amount of queries left\n // state.queryCounter : sequence for current query\n // state.maxedQueries : queries that resulted in more than serverMaxResults hits\n\n async function iterate({initialState = {}, matches = [], candidateCount = 0, nonMatches = [], duplicateCount = 0, nonMatchCount = 0, conversionFailures = [], matchErrors = []}) {\n debugData(`Starting next matcher iteration.`);\n const {records, failures, ...state} = await search(initialState);\n\n debugData(`Current state: ${JSON.stringify(state)}, matches: ${matches.length}, candidateCount: ${candidateCount}, nonMatches: ${nonMatches.length}, nonMatchCount: ${nonMatchCount}, conversionFailures: ${conversionFailures}, matchErrors: ${matchErrors.length}`);\n const recordSetSize = records.length;\n const failureSetSize = failures.length;\n const newCandidateCount = candidateCount + recordSetSize + failureSetSize;\n\n const newConversionFailures = conversionFailures.concat(failures);\n debugData(`Failures: ${failures.length}, ConversionFailures: ${conversionFailures.length}, NewConversionFailures: ${newConversionFailures.length}`);\n\n if (recordSetSize > 0) {\n return handleRecordSet();\n }\n\n if (state.queriesLeft > 0) {\n debug(`Empty record set ${state.searchCounter} for ${state.query}, but there are ${state.queriesLeft} queries left`);\n return iterate({initialState: state, matches, candidateCount: newCandidateCount, nonMatches, nonMatchCount, duplicateCount, conversionFailures: newConversionFailures, matchErrors});\n }\n\n debug(`No (more) candidate records to check, no more queries left, matches: ${matches.length}`);\n return returnResult({matches, state, stopReason: '', nonMatches, nonMatchCount, candidateCount: newCandidateCount, duplicateCount, conversionFailures: newConversionFailures, matchErrors});\n\n function handleRecordSet() {\n debug(`Checking record set of ${recordSetSize} candidate records for possible matches, found by ${state.searchCounter} search for ${state.query}`);\n\n const matchResult = iterateRecords({records, recordSetSize, maxMatches, matches, nonMatches, nonMatchCount});\n\n const newDuplicateCount = duplicateCount + matchResult.duplicateCount;\n const newNonMatchCount = nonMatchCount + matchResult.nonMatchCount;\n const {newMatches, newNonMatches, newMatchErrors} = handleMatchResult(matchResult, matches, nonMatches, matchErrors);\n\n if (maxMatchesFound({matches: newMatches, maxMatches})) {\n return returnResult({matches: newMatches, state, stopReason: 'maxMatches', nonMatches: newNonMatches, duplicateCount: newDuplicateCount, candidateCount: newCandidateCount, nonMatchCount: newNonMatchCount, conversionFailures: newConversionFailures, matchErrors: newMatchErrors});\n }\n\n if (maxCandidatesRetrieved(newCandidateCount, maxCandidates)) {\n return returnResult({matches: newMatches, state, stopReason: 'maxCandidates', nonMatches: newNonMatches, duplicateCount: newDuplicateCount, candidateCount: newCandidateCount, nonMatchCount: newNonMatchCount, conversionFailures: newConversionFailures, matchErrors: newMatchErrors});\n }\n\n return iterate({initialState: state, matches: newMatches, candidateCount: newCandidateCount, nonMatches: newNonMatches, duplicateCount: newDuplicateCount, nonMatchCount: newNonMatchCount, conversionFailures: newConversionFailures, matchErrors: newMatchErrors});\n }\n\n function handleMatchResult(matchResult, matches, nonMatches, matchErrors) {\n debugData(`- Amount of new matches from record set: ${matchResult.matches.length}`);\n // eslint-disable-next-line functional/no-conditional-statement\n if (returnNonMatches) {\n debugData(`- Amount of new nonMatches from record set: ${matchResult.nonMatches.length}`);\n }\n\n const newMatches = matches.concat(returnQuery ? addQuery(matchResult.matches) : matchResult.matches);\n const newNonMatches = returnNonMatches ? nonMatches.concat(returnQuery ? addQuery(matchResult.nonMatches) : matchResult.nonMatches) : [];\n const newMatchErrors = matchErrors.concat(matchResult.matchErrors);\n\n debugData(`- Total amount of matches: ${newMatches.length}`);\n // eslint-disable-next-line functional/no-conditional-statement\n if (returnNonMatches) {\n debugData(`- Total amount of nonMatches: ${newNonMatches.length}`);\n }\n\n debugData(`MatchResult: ${JSON.stringify(matchResult)}`);\n debugData(`Old matchErrors: ${JSON.stringify(matchErrors)}, matchErrors from matchResult: ${JSON.stringify(matchResult.matchErrors)}, New matchErrors: ${JSON.stringify(newMatchErrors)}`);\n\n debugData(`- Total amount of matchErrors: ${newMatchErrors.length}`);\n\n return {newMatches, newNonMatches, newMatchErrors};\n }\n\n function addQuery(matches) {\n debugData(`Adding query ${state.query} to matches`);\n return matches.map((match) => ({...match, matchQuery: state.query}));\n }\n\n function maxCandidatesRetrieved(candidateCount, maxCandidates) {\n debugData(`Total amount of candidate records retrieved: ${newCandidateCount} (max: ${maxCandidates})`);\n if (maxCandidates && candidateCount >= maxCandidates) {\n debug(`Stopped matching because maximum number of candidate records ${candidateCount} / ${maxCandidates} have been retrieved`);\n return true;\n }\n }\n }\n\n // matches : array of matching candidate records\n // nonMatches : array of nonMatching candidate records (if returnNonMatches option is true, otherwise empty array)\n // - candidate.id\n // - candidate.record\n // - probability\n // - strategy (if returnStrategy option is true)\n // - treshold (if returnStrategy option is true)\n // - matchQuery (if returnQuery option is true)\n // failures: array of conversionFailures from candidate-search and matchErrors from matchDetection in error format {status, payload: {message, id}} if returnFailures is true\n\n // we could have here also returnRecords/returnMatchRecords/returnNonMatchRecord options that could be turned false for not to return actual record data\n\n // matchStatus.status: boolean, true if matcher retrieved and handled all found candidate records, false if it did not\n // matchStatus.stopReason: string ('maxMatches','maxCandidates','maxedQueries','conversionFailures', empty string/undefined), reason for stopping retrieving or handling the candidate records\n // - only one stopReason is returned (if there would be several possible stopReasons, stopReason is picked in the above order)\n // - currently stopReason can be non-empty also in cases where status is true, if matcher hit the stop reason when handling the last available candidate record\n\n function returnResult({matches, state, stopReason, nonMatches, duplicateCount, candidateCount, nonMatchCount, conversionFailures, matchErrors}) {\n const conversionFailureCount = conversionFailures.length;\n const matchErrorCount = matchErrors.length;\n checkCounts({matches, nonMatches, candidateCount, duplicateCount, nonMatchCount, conversionFailureCount, matchErrorCount});\n const matchStatus = getMatchState(state, stopReason, conversionFailureCount, matchErrorCount);\n // add nonMatches to result only if returnNonMatches is 'true', otherwise nonMatches have not been gathered\n const matchesResult = returnNonMatches ? {matches, matchStatus, nonMatches} : {matches, matchStatus};\n const failures = [...conversionFailures, ...matchErrors];\n const result = returnFailures ? {...matchesResult, conversionFailures: failures} : matchesResult;\n debugData(`ReturnFailures ${returnFailures}`);\n debugData(`${JSON.stringify(result)}`);\n return result;\n\n // note that in cases where the matching has been stopped because of maxMatches checkCounts won't (in most cases) match\n\n function checkCounts({matches, nonMatches, candidateCount, duplicateCount, nonMatchCount, conversionFailureCount, matchErrorCount}) {\n const matchCount = matches.length;\n debugData(`Return nonMatches: ${returnNonMatches}`);\n const chosenNonMatchCount = returnNonMatches ? nonMatches.length : nonMatchCount;\n const totalHandled = matchCount + chosenNonMatchCount + duplicateCount;\n debug(`candidateCount: ${candidateCount}, matches: ${matchCount}, nonMatches: ${chosenNonMatchCount}, duplicateCount: ${duplicateCount}, conversionFailureCount: ${conversionFailureCount}, matchErrorCount: ${matchErrorCount}`);\n debug(`We got result for ${totalHandled} / ${candidateCount} retrieved candidates`);\n if (totalHandled !== candidateCount) {\n debug(`WARNING: Missing results for ${candidateCount - totalHandled} candidates`);\n return;\n }\n return;\n }\n\n // eslint-disable-next-line max-statements\n function getMatchState(state, stopReason, conversionFailuresCount, matchErrorCount) {\n debugData(`${JSON.stringify(state)}`);\n debug(`We had ${conversionFailuresCount} retrieved candidates that could not be converted.`);\n debug(`We had ${matchErrorCount} retrieved candidates that errored in matchDetection.`);\n debug(`Queries left ${state.queriesLeft}, Searches for current query left: ${state.resultSetOffset && state.resultSetOffset <= state.totalRecords}, non-retrieved records: ${state.totalRecords - state.queryCandidateCounter}, maxedQueries (${state.maxedQueries.length}): ${state.maxedQueries}`);\n\n debugData(`StopReason: <${stopReason}>`);\n\n const searchesLeft = state.resultSetOffset && state.resultSetOffset <= state.totalRecords;\n const nonRetrieved = searchesLeft ? state.totalRecords - state.queryCandidateCounter : 0;\n debugData(`nonRetrieved: ${nonRetrieved}`);\n\n // matchStatus.stopReason: string ('maxMatches','maxCandidates','maxedQueries','conversionFailures', empty string/undefined), reason for stopping retrieving or handling the candidate records\n // 'maxMatches' and 'maxCandidates' are in stopReason, 'maxedQueries', 'conversionFailures' and 'matchErrors' are created here\n\n if (state.queriesLeft > 0 || nonRetrieved > 0 || state.maxedQueries.length > 0 || conversionFailureCount > 0 || matchErrorCount > 0) {\n const maxedQueriesStopReason = state.maxedQueries.length > 0 ? 'maxedQueries' : undefined;\n const conversionFailuresStopReason = conversionFailureCount > 0 ? 'conversionFailures' : undefined;\n const matchErrorsStopReason = matchErrorCount > 0 ? 'matchErrors' : undefined;\n const newStopReason = stopReason === '' || stopReason === undefined ? maxedQueriesStopReason || conversionFailuresStopReason || matchErrorsStopReason : stopReason;\n debugData(`MaxedQueriesStopReason: <${maxedQueriesStopReason}>`);\n debugData(`ConversionFailureStopReason <${conversionFailuresStopReason}>`);\n debugData(`MatchErrorsStopReason <${matchErrorsStopReason}>`);\n debugData(`NewStopReason: <${newStopReason}>`);\n debug(`Match status: false`);\n return {status: false, stopReason: newStopReason};\n }\n\n debug(`Match status: true`);\n return {status: true, stopReason};\n }\n }\n\n // NOTES:\n // - we could optimize by creating the featureSet for the incoming record once and using it for all database/candidateRecords\n // - if creating the featureSet for the incoming record fails we have an unprocessable entity\n // - if creating the featureSet for a candidate record fails we could skip that candidate - but list the case as a detectionFailure, same as conversionFailures\n\n // eslint-disable-next-line max-statements\n function iterateRecords({records, recordSetSize, maxMatches, matches = [], nonMatches = [], recordMatches = [], recordNonMatches = [], recordCount = 0, recordDuplicateCount = 0, recordNonMatchCount = 0, recordMatchErrors = []}) {\n\n // recordSetSize : total amount of records in the current record set\n // recordCount : amount of records from the current record set that have been handled\n // maxMatches : setting for maximum amount found by current matcher job before the matcher job is stopped\n // recordDuplicateCount : amount of records from the current record set that are already included in matches/nonMatches results\n // recordNonMatchCount: amount of records from the current record set that are nonMatches (only is returnNonMatches setting is false)\n\n // records : non-handled records in the current record set\n // matches : found matches in the current matcher job\n // recordMatches : found matches in the current record set\n // recordNonMatches : found nonMatches in the current record set (only if returnNonMatches setting is true)\n // recordMatchErrors: errored matchDetection in the current record set\n\n const [candidate] = records;\n const newRecordCount = candidate ? recordCount + 1 : recordCount;\n\n // The matcher uses same matchDetection strategy for candidates from all candidate-searches -> matchDetection result for the same candidate is always same\n // Exceptions would happen if the candidate would have been updated in the database between candidate searches\n // Note that if returnNonMatches is false, matcher won't remember candidates that didn't match, so they will be matched again everytime they are retrieved by\n // different candidate search queries. Same candidate search query won't have duplicate records.\n\n /* We could optimize and detect all retrieved candidates at once\n const candidateRecords = records.map(record => record.record);\n const recordsIsArray = Array.isArray(candidateRecords);\n debug(`records is an array: ${recordsIsArray}`);\n const result = detect(record, candidateRecords);\n debug(`${JSON.stringify(result)}`);\n */\n\n if (candidate) {\n\n // eslint-disable-next-line functional/no-conditional-statement\n if (candidateNotInMatches(matches.concat(nonMatches), candidate)) {\n const {record: candidateRecord, id: candidateId} = candidate;\n try {\n debug(`Running matchDetection for record ${candidateId} (${newRecordCount}/${recordSetSize})`);\n // we should handle errors from detection somehow - ie. cases where either record or candidateRecord errors\n const detectionResult = detect(record, candidateRecord);\n\n return handleDetectionResult(detectionResult, candidateId, candidateRecord);\n } catch (error) {\n debug(`MatchDetection errored: database record ${candidateId}: ${error}`);\n\n const matchError = {status: 422, payload: {message: `Matching errored for database record ${candidateId}. ${error.message}.`, id: candidateId}};\n const newRecordMatchErrors = recordMatchErrors.concat(matchError);\n return iterateRecords({records: records.slice(1), recordSetSize, maxMatches, matches, recordMatches, recordCount: newRecordCount, recordNonMatches, recordDuplicateCount, recordNonMatchCount, recordMatchErrors: newRecordMatchErrors});\n }\n }\n\n return iterateRecords({records: records.slice(1), recordSetSize, maxMatches, matches, recordMatches, recordCount: newRecordCount, recordNonMatches, recordDuplicateCount: recordDuplicateCount + 1, recordNonMatchCount, recordMatchErrors});\n }\n\n debug(`No more candidates, record set (${recordCount}/${recordSetSize}) done, ${recordMatches.length} matches found, ${recordDuplicateCount} candidates already handled, ${returnNonMatches ? `${recordNonMatches.length}` : `${recordNonMatchCount}`} nonMatches found.`);\n return {matches: recordMatches, nonMatches: returnNonMatches ? recordNonMatches : [], duplicateCount: recordDuplicateCount, nonMatchCount: recordNonMatchCount, matchErrors: recordMatchErrors};\n\n function handleDetectionResult(detectionResult, candidateId, candidateRecord) {\n debugData(`MatchDetection results for ${candidateId} (${newRecordCount}/${recordSetSize}): ${JSON.stringify(detectionResult)}`);\n\n if (detectionResult.match || returnNonMatches) {\n debug(`${detectionResult.match ? `Record ${candidateId} (${newRecordCount}/${recordSetSize}) is a match!` : `Record ${candidateId} (${newRecordCount}/${recordSetSize}) is NOT a match!`}`);\n debugData(`Strategy: ${JSON.stringify(detectionResult.strategy)}, Treshold: ${JSON.stringify(detectionResult.treshold)}`);\n\n const matchResult = {\n probability: detectionResult.probability,\n candidate: {\n id: candidateId,\n record: candidateRecord\n }\n };\n const strategyResult = {\n strategy: detectionResult.strategy,\n treshold: detectionResult.treshold\n };\n const newMatch = returnStrategy ? {...matchResult, ...strategyResult} : {...matchResult};\n\n debugData(`${JSON.stringify(newMatch)}`);\n\n return handleRecordMatch(detectionResult.match, newMatch);\n }\n\n const newRecordNonMatchCount = recordNonMatchCount + 1;\n debugData(`- Total nonMatches after this detection: ${newRecordNonMatchCount}`);\n\n return iterateRecords({records: records.slice(1), recordSetSize, maxMatches, matches, recordMatches, recordCount: newRecordCount, recordNonMatches, recordDuplicateCount, recordNonMatchCount: newRecordNonMatchCount, recordMatchErrors});\n }\n\n function handleRecordMatch(isMatch, newMatch) {\n const newRecordMatches = isMatch ? recordMatches.concat(newMatch) : recordMatches;\n const newRecordNonMatches = isMatch ? recordNonMatches : recordNonMatches.concat(newMatch);\n const newRecordNonMatchCount = isMatch ? recordNonMatchCount : recordNonMatchCount + 1;\n\n debugData(`- Total matches after this detection: ${matches.concat(newRecordMatches).length} (max: ${maxMatches})`);\n\n // eslint-disable-next-line functional/no-conditional-statement\n if (returnNonMatches) {\n debugData(`- Total nonMatches after this detection: ${nonMatches.concat(newRecordNonMatches).length}`);\n }\n debugData(`- Total nonMatchCount after this detection: ${recordNonMatchCount}`);\n\n if (maxMatchesFound({matches: matches.concat(newRecordMatches), maxMatches})) {\n debug(`MaxMatches (${maxMatches}) reached, handled candidates in record set: ${newRecordCount} non-handled candidates in record set ${recordSetSize - newRecordCount}`);\n return {matches: newRecordMatches, nonMatches: returnNonMatches ? newRecordNonMatches : [], duplicateCount: recordDuplicateCount, nonMatchCount: newRecordNonMatchCount, matchErrors: recordMatchErrors};\n }\n\n return iterateRecords({records: records.slice(1), recordSetSize, maxMatches, matches, recordMatches: newRecordMatches, recordCount: newRecordCount, recordNonMatches: returnNonMatches ? newRecordNonMatches : [], duplicateCount: recordDuplicateCount, recordNonMatchCount: newRecordNonMatchCount, matchErrors: recordMatchErrors});\n }\n\n function candidateNotInMatches(matches, candidate) {\n debug(`Checking that record ${candidate.id} is not already included in ${matches.length} matches/nonMatches`);\n const newCandidateId = candidate.id;\n debugData(`newCandidateId: ${newCandidateId}`);\n const result = matches.find(({candidate}) => candidate.id === newCandidateId);\n debugData(`Result: ${result}`);\n if (result) {\n debug(`${candidate.id} was already handled.`);\n return false;\n }\n debug(`${candidate.id} not found in matches/nonMatches`);\n return true;\n }\n }\n\n function maxMatchesFound({matches, maxMatches}) {\n if (maxMatches && matches.length >= maxMatches) {\n debug(`Stopping recordSet iteration: maxMatches (${maxMatches}) for matcher job found.`);\n return true;\n }\n }\n };\n};\n"],"file":"index.js"}
@@ -56,7 +56,7 @@ var _default = ({
56
56
  }) {
57
57
  if (code === 'a') {
58
58
  return {
59
- name: value.replace(/[^\p{Letter}\p{Number}]/gu, '').toLowerCase()
59
+ name: value ? value.replace(/[^\p{Letter}\p{Number}]/gu, '').toLowerCase() : ''
60
60
  };
61
61
  }
62
62
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/match-detection/features/bib/authors.js"],"names":["nameTreshold","name","extract","record","get","map","subfields","filter","code","value","includes","toObj","reduce","acc","v","replace","toLowerCase","id","compare","a","b","maxAuthors","length","matchingIds","findMatchingIds","matchingNames","findMatchingNames","idPoints","namePoints","totalPoints","findMatches","distance","maxLength","getMaxLength","percentage","key","cb","valuesA","o","valuesB","allValues","concat","occurrance","otherValue"],"mappings":"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","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 {LevenshteinDistance as leven} from 'natural';\n\nexport default ({nameTreshold = 10} = {}) => ({\n name: 'Authors',\n extract: record => record.get(/^(?<def>100|700)$/u)\n .map(({subfields}) => {\n return subfields\n .filter(({code, value}) => code && value)\n .filter(({code}) => ['a', '0'].includes(code))\n .map(toObj)\n .reduce((acc, v) => ({...acc, ...v}), {});\n\n function toObj({code, value}) {\n if (code === 'a') {\n return {name: value.replace(/[^\\p{Letter}\\p{Number}]/gu, '').toLowerCase()};\n }\n\n return {id: value};\n }\n }),\n compare: (a, b) => {\n const maxAuthors = a.length > b.length ? a.length : b.length;\n const matchingIds = findMatchingIds();\n\n if (maxAuthors >= 3 && matchingIds >= 3) {\n return 0.3;\n }\n\n const matchingNames = findMatchingNames();\n const idPoints = matchingIds / maxAuthors * 0.3;\n const namePoints = matchingNames / maxAuthors * 0.2;\n const totalPoints = idPoints + namePoints;\n\n return totalPoints <= 0.2 ? totalPoints : 0.2;\n\n function findMatchingIds() {\n return findMatches('id', (a, b) => a === b);\n }\n\n function findMatchingNames() {\n return findMatches('name', (a, b) => {\n const distance = leven(a, b);\n\n if (distance === 0) {\n return true;\n }\n\n const maxLength = getMaxLength();\n const percentage = distance / maxLength * 100;\n\n return percentage <= nameTreshold;\n\n function getMaxLength() {\n return a.length > b.length ? a.length : b.length;\n }\n });\n }\n\n function findMatches(key, cb) {\n const valuesA = a.filter(o => o[key]).map(o => o[key]);\n const valuesB = b.filter(o => o[key]).map(o => o[key]);\n const allValues = valuesA.concat(valuesB);\n\n return allValues.reduce((acc, value) => {\n const occurrance = allValues.filter(otherValue => cb(value, otherValue)).length;\n return occurrance >= 2 ? acc + 1 : acc;\n }, 0);\n }\n }\n});\n"],"file":"authors.js"}
1
+ {"version":3,"sources":["../../../../src/match-detection/features/bib/authors.js"],"names":["nameTreshold","name","extract","record","get","map","subfields","filter","code","value","includes","toObj","reduce","acc","v","replace","toLowerCase","id","compare","a","b","maxAuthors","length","matchingIds","findMatchingIds","matchingNames","findMatchingNames","idPoints","namePoints","totalPoints","findMatches","distance","maxLength","getMaxLength","percentage","key","cb","valuesA","o","valuesB","allValues","concat","occurrance","otherValue"],"mappings":";;;;;;;AA4BA;;AA5BA;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;eAIe,CAAC;AAACA,EAAAA,YAAY,GAAG;AAAhB,IAAsB,EAAvB,MAA+B;AAC5CC,EAAAA,IAAI,EAAE,SADsC;AAE5CC,EAAAA,OAAO,EAAEC,MAAM,IAAIA,MAAM,CAACC,GAAP,CAAW,oBAAX,EAChBC,GADgB,CACZ,CAAC;AAACC,IAAAA;AAAD,GAAD,KAAiB;AACpB,WAAOA,SAAS,CACbC,MADI,CACG,CAAC;AAACC,MAAAA,IAAD;AAAOC,MAAAA;AAAP,KAAD,KAAmBD,IAAI,IAAIC,KAD9B,EAEJF,MAFI,CAEG,CAAC;AAACC,MAAAA;AAAD,KAAD,KAAY,CAAC,GAAD,EAAM,GAAN,EAAWE,QAAX,CAAoBF,IAApB,CAFf,EAGJH,GAHI,CAGAM,KAHA,EAIJC,MAJI,CAIG,CAACC,GAAD,EAAMC,CAAN,MAAa,EAAC,GAAGD,GAAJ;AAAS,SAAGC;AAAZ,KAAb,CAJH,EAIiC,EAJjC,CAAP;;AAMA,aAASH,KAAT,CAAe;AAACH,MAAAA,IAAD;AAAOC,MAAAA;AAAP,KAAf,EAA8B;AAC5B,UAAID,IAAI,KAAK,GAAb,EAAkB;AAChB,eAAO;AAACP,UAAAA,IAAI,EAAEQ,KAAK,GAAGA,KAAK,CAACM,OAAN,CAAc,2BAAd,EAA2C,EAA3C,EAA+CC,WAA/C,EAAH,GAAkE;AAA9E,SAAP;AACD;;AAED,aAAO;AAACC,QAAAA,EAAE,EAAER;AAAL,OAAP;AACD;AACF,GAfgB,CAFyB;AAkB5CS,EAAAA,OAAO,EAAE,CAACC,CAAD,EAAIC,CAAJ,KAAU;AACjB,UAAMC,UAAU,GAAGF,CAAC,CAACG,MAAF,GAAWF,CAAC,CAACE,MAAb,GAAsBH,CAAC,CAACG,MAAxB,GAAiCF,CAAC,CAACE,MAAtD;AACA,UAAMC,WAAW,GAAGC,eAAe,EAAnC;;AAEA,QAAIH,UAAU,IAAI,CAAd,IAAmBE,WAAW,IAAI,CAAtC,EAAyC;AACvC,aAAO,GAAP;AACD;;AAED,UAAME,aAAa,GAAGC,iBAAiB,EAAvC;AACA,UAAMC,QAAQ,GAAGJ,WAAW,GAAGF,UAAd,GAA2B,GAA5C;AACA,UAAMO,UAAU,GAAGH,aAAa,GAAGJ,UAAhB,GAA6B,GAAhD;AACA,UAAMQ,WAAW,GAAGF,QAAQ,GAAGC,UAA/B;AAEA,WAAOC,WAAW,IAAI,GAAf,GAAqBA,WAArB,GAAmC,GAA1C;;AAEA,aAASL,eAAT,GAA2B;AACzB,aAAOM,WAAW,CAAC,IAAD,EAAO,CAACX,CAAD,EAAIC,CAAJ,KAAUD,CAAC,KAAKC,CAAvB,CAAlB;AACD;;AAED,aAASM,iBAAT,GAA6B;AAC3B,aAAOI,WAAW,CAAC,MAAD,EAAS,CAACX,CAAD,EAAIC,CAAJ,KAAU;AACnC,cAAMW,QAAQ,GAAG,kCAAMZ,CAAN,EAASC,CAAT,CAAjB;;AAEA,YAAIW,QAAQ,KAAK,CAAjB,EAAoB;AAClB,iBAAO,IAAP;AACD;;AAED,cAAMC,SAAS,GAAGC,YAAY,EAA9B;AACA,cAAMC,UAAU,GAAGH,QAAQ,GAAGC,SAAX,GAAuB,GAA1C;AAEA,eAAOE,UAAU,IAAIlC,YAArB;;AAEA,iBAASiC,YAAT,GAAwB;AACtB,iBAAOd,CAAC,CAACG,MAAF,GAAWF,CAAC,CAACE,MAAb,GAAsBH,CAAC,CAACG,MAAxB,GAAiCF,CAAC,CAACE,MAA1C;AACD;AACF,OAfiB,CAAlB;AAgBD;;AAED,aAASQ,WAAT,CAAqBK,GAArB,EAA0BC,EAA1B,EAA8B;AAC5B,YAAMC,OAAO,GAAGlB,CAAC,CAACZ,MAAF,CAAS+B,CAAC,IAAIA,CAAC,CAACH,GAAD,CAAf,EAAsB9B,GAAtB,CAA0BiC,CAAC,IAAIA,CAAC,CAACH,GAAD,CAAhC,CAAhB;AACA,YAAMI,OAAO,GAAGnB,CAAC,CAACb,MAAF,CAAS+B,CAAC,IAAIA,CAAC,CAACH,GAAD,CAAf,EAAsB9B,GAAtB,CAA0BiC,CAAC,IAAIA,CAAC,CAACH,GAAD,CAAhC,CAAhB;AACA,YAAMK,SAAS,GAAGH,OAAO,CAACI,MAAR,CAAeF,OAAf,CAAlB;AAEA,aAAOC,SAAS,CAAC5B,MAAV,CAAiB,CAACC,GAAD,EAAMJ,KAAN,KAAgB;AACtC,cAAMiC,UAAU,GAAGF,SAAS,CAACjC,MAAV,CAAiBoC,UAAU,IAAIP,EAAE,CAAC3B,KAAD,EAAQkC,UAAR,CAAjC,EAAsDrB,MAAzE;AACA,eAAOoB,UAAU,IAAI,CAAd,GAAkB7B,GAAG,GAAG,CAAxB,GAA4BA,GAAnC;AACD,OAHM,EAGJ,CAHI,CAAP;AAID;AACF;AAlE2C,CAA/B,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 {LevenshteinDistance as leven} from 'natural';\n\nexport default ({nameTreshold = 10} = {}) => ({\n name: 'Authors',\n extract: record => record.get(/^(?<def>100|700)$/u)\n .map(({subfields}) => {\n return subfields\n .filter(({code, value}) => code && value)\n .filter(({code}) => ['a', '0'].includes(code))\n .map(toObj)\n .reduce((acc, v) => ({...acc, ...v}), {});\n\n function toObj({code, value}) {\n if (code === 'a') {\n return {name: value ? value.replace(/[^\\p{Letter}\\p{Number}]/gu, '').toLowerCase() : ''};\n }\n\n return {id: value};\n }\n }),\n compare: (a, b) => {\n const maxAuthors = a.length > b.length ? a.length : b.length;\n const matchingIds = findMatchingIds();\n\n if (maxAuthors >= 3 && matchingIds >= 3) {\n return 0.3;\n }\n\n const matchingNames = findMatchingNames();\n const idPoints = matchingIds / maxAuthors * 0.3;\n const namePoints = matchingNames / maxAuthors * 0.2;\n const totalPoints = idPoints + namePoints;\n\n return totalPoints <= 0.2 ? totalPoints : 0.2;\n\n function findMatchingIds() {\n return findMatches('id', (a, b) => a === b);\n }\n\n function findMatchingNames() {\n return findMatches('name', (a, b) => {\n const distance = leven(a, b);\n\n if (distance === 0) {\n return true;\n }\n\n const maxLength = getMaxLength();\n const percentage = distance / maxLength * 100;\n\n return percentage <= nameTreshold;\n\n function getMaxLength() {\n return a.length > b.length ? a.length : b.length;\n }\n });\n }\n\n function findMatches(key, cb) {\n const valuesA = a.filter(o => o[key]).map(o => o[key]);\n const valuesB = b.filter(o => o[key]).map(o => o[key]);\n const allValues = valuesA.concat(valuesB);\n\n return allValues.reduce((acc, value) => {\n const occurrance = allValues.filter(otherValue => cb(value, otherValue)).length;\n return occurrance >= 2 ? acc + 1 : acc;\n }, 0);\n }\n }\n});\n"],"file":"authors.js"}
@@ -54,12 +54,13 @@ var _default = ({
54
54
  if (field) {
55
55
  return field.subfields.filter(({
56
56
  code
57
- }) => subfieldCodes.includes(code)).map(({
57
+ }) => subfieldCodes.includes(code)) // .map(({code, value}) => ({code, value: value.replace(/-/ug, '')}));
58
+ .map(({
58
59
  code,
59
60
  value
60
61
  }) => ({
61
62
  code,
62
- value: value.replace(/-/ug, '')
63
+ value: value ? value.replace(/-/ug, '') : ''
63
64
  }));
64
65
  }
65
66
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/match-detection/features/bib/standard-identifier-factory.js"],"names":["debug","debugData","extend","pattern","subfieldCodes","extract","compare","record","field","get","subfields","filter","code","includes","map","value","replace","a","b","length","bothHaveValidIdentifiers","maxValues","matchingValues","getValueCount","aValues","bValues","validOnly","getIdentifiers","aValue","some","bValue","values"],"mappings":"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","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';\n\nconst debug = createDebugLogger('@natlibfi/melinda-record-matching:match-detection:features:standard-identifiers');\nconst debugData = debug.extend('data');\n\nexport default ({pattern, subfieldCodes}) => {\n return {extract, compare};\n\n function extract(record) {\n const [field] = record.get(pattern);\n\n if (field) {\n return field.subfields\n .filter(({code}) => subfieldCodes.includes(code))\n .map(({code, value}) => ({code, value: value.replace(/-/ug, '')}));\n }\n\n return [];\n }\n\n function compare(a, b) {\n if (a.length === 0 || b.length === 0) {\n debugData(`No standardidentifiers to compare`);\n return 0;\n }\n\n if (bothHaveValidIdentifiers()) {\n const {maxValues, matchingValues} = getValueCount(true);\n return matchingValues / maxValues * 0.75;\n }\n\n const {maxValues, matchingValues} = getValueCount();\n return matchingValues / maxValues * 0.2;\n\n function bothHaveValidIdentifiers() {\n const aValues = a.filter(({code}) => code === 'a');\n const bValues = a.filter(({code}) => code === 'a');\n return aValues.length > 0 && bValues.length > 0;\n }\n\n function getValueCount(validOnly = false) {\n const aValues = getIdentifiers(a);\n const bValues = getIdentifiers(b);\n\n return {\n maxValues: aValues.length > bValues.length ? aValues.length : bValues.length,\n matchingValues: aValues.filter(aValue => bValues.some(bValue => aValue === bValue)).length\n };\n\n function getIdentifiers(values) {\n if (validOnly) {\n return values\n .filter(({code}) => code === 'a')\n .map(({value}) => value);\n }\n\n return values.map(({value}) => value);\n }\n }\n }\n};\n"],"file":"standard-identifier-factory.js"}
1
+ {"version":3,"sources":["../../../../src/match-detection/features/bib/standard-identifier-factory.js"],"names":["debug","debugData","extend","pattern","subfieldCodes","extract","compare","record","field","get","subfields","filter","code","includes","map","value","replace","a","b","length","bothHaveValidIdentifiers","maxValues","matchingValues","getValueCount","aValues","bValues","validOnly","getIdentifiers","aValue","some","bValue","values"],"mappings":"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","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';\n\nconst debug = createDebugLogger('@natlibfi/melinda-record-matching:match-detection:features:standard-identifiers');\nconst debugData = debug.extend('data');\n\nexport default ({pattern, subfieldCodes}) => {\n return {extract, compare};\n\n function extract(record) {\n const [field] = record.get(pattern);\n\n if (field) {\n return field.subfields\n .filter(({code}) => subfieldCodes.includes(code))\n // .map(({code, value}) => ({code, value: value.replace(/-/ug, '')}));\n .map(({code, value}) => ({code, value: value ? value.replace(/-/ug, '') : ''}));\n }\n\n return [];\n }\n\n function compare(a, b) {\n if (a.length === 0 || b.length === 0) {\n debugData(`No standardidentifiers to compare`);\n return 0;\n }\n\n if (bothHaveValidIdentifiers()) {\n const {maxValues, matchingValues} = getValueCount(true);\n return matchingValues / maxValues * 0.75;\n }\n\n const {maxValues, matchingValues} = getValueCount();\n return matchingValues / maxValues * 0.2;\n\n function bothHaveValidIdentifiers() {\n const aValues = a.filter(({code}) => code === 'a');\n const bValues = a.filter(({code}) => code === 'a');\n return aValues.length > 0 && bValues.length > 0;\n }\n\n function getValueCount(validOnly = false) {\n const aValues = getIdentifiers(a);\n const bValues = getIdentifiers(b);\n\n return {\n maxValues: aValues.length > bValues.length ? aValues.length : bValues.length,\n matchingValues: aValues.filter(aValue => bValues.some(bValue => aValue === bValue)).length\n };\n\n function getIdentifiers(values) {\n if (validOnly) {\n return values\n .filter(({code}) => code === 'a')\n .map(({value}) => value);\n }\n\n return values.map(({value}) => value);\n }\n }\n }\n};\n"],"file":"standard-identifier-factory.js"}
@@ -46,7 +46,6 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
46
46
  * for the JavaScript code in this file.
47
47
  *
48
48
  */
49
- // eslint-disable-next-line max-statements
50
49
  var _default = ({
51
50
  strategy,
52
51
  treshold = 0.9
@@ -58,26 +57,43 @@ var _default = ({
58
57
  debugData(`Treshold: ${JSON.stringify(treshold)}`);
59
58
  debugData(`ReturnStrategy: ${JSON.stringify(returnStrategy)}`);
60
59
  const featuresA = extractFeatures(recordA);
61
- const featuresB = extractFeatures(recordB);
62
- debugData(`Features (a): ${JSON.stringify(featuresA)}`);
63
- debugData(`Features (b): ${JSON.stringify(featuresB)}`);
64
- const featurePairs = generateFeaturePairs();
65
- const similarityVector = generateSimilarityVector();
66
-
67
- if (similarityVector.some(v => v >= minProbabilityQuantifier)) {
68
- const probability = calculateprobability();
69
- debug(`probability: ${probability} (Treshold: ${treshold})`);
60
+ debug(`We got an array of records: ${Array.isArray(recordB)}`);
61
+ const recordsB = Array.isArray(recordB) ? recordB : [recordB];
62
+ const detectionResults = recordsB.map(record => actualDetection(featuresA, record));
63
+ return Array.isArray(recordB) ? detectionResults : detectionResults[0];
64
+
65
+ function actualDetection(featuresA, record) {
66
+ const featuresB = extractFeatures(record);
67
+ debugData(`Features (a): ${JSON.stringify(featuresA)}`);
68
+ debugData(`Features (b): ${JSON.stringify(featuresB)}`);
69
+ const featurePairs = generateFeaturePairs(featuresA, featuresB);
70
+ const similarityVector = generateSimilarityVector(featurePairs);
71
+
72
+ if (similarityVector.some(v => v >= minProbabilityQuantifier)) {
73
+ const probability = calculateprobability(similarityVector);
74
+ debug(`probability: ${probability} (Treshold: ${treshold})`);
75
+ return returnResult({
76
+ match: probability >= treshold,
77
+ probability
78
+ });
79
+ }
80
+
81
+ debugData(`No feature yielded minimum probability amount of points (${minProbabilityQuantifier})`);
70
82
  return returnResult({
71
- match: probability >= treshold,
72
- probability
83
+ match: false,
84
+ probability: 0.0
73
85
  });
74
86
  }
75
87
 
76
- debugData(`No feature yielded minimum probability amount of points (${minProbabilityQuantifier})`);
77
- return returnResult({
78
- match: false,
79
- probability: 0.0
80
- });
88
+ function extractFeatures(record) {
89
+ return strategy.reduce((acc, {
90
+ name,
91
+ extract
92
+ }) => acc.concat({
93
+ name,
94
+ value: extract(record)
95
+ }), []);
96
+ }
81
97
 
82
98
  function returnResult(result) {
83
99
  if (returnStrategy) {
@@ -100,22 +116,12 @@ var _default = ({
100
116
  return strategyNames || [];
101
117
  }
102
118
 
103
- function calculateprobability() {
119
+ function calculateprobability(similarityVector) {
104
120
  const probability = similarityVector.reduce((acc, v) => acc + v, 0.0);
105
121
  return probability > 1.0 ? 1.0 : probability;
106
122
  }
107
123
 
108
- function extractFeatures(record) {
109
- return strategy.reduce((acc, {
110
- name,
111
- extract
112
- }) => acc.concat({
113
- name,
114
- value: extract(record)
115
- }), []);
116
- }
117
-
118
- function generateSimilarityVector() {
124
+ function generateSimilarityVector(featurePairs) {
119
125
  const compared = featurePairs.map(({
120
126
  name,
121
127
  a,
@@ -138,7 +144,7 @@ var _default = ({
138
144
  }) => points);
139
145
  }
140
146
 
141
- function generateFeaturePairs() {
147
+ function generateFeaturePairs(featuresA, featuresB) {
142
148
  const pairs = generatePairs();
143
149
  const missingFeatures = findMissing();
144
150
  debug(`Not comparing the following features because one, or both records are missing features: ${JSON.stringify(missingFeatures)}`);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/match-detection/index.js"],"names":["strategy","treshold","returnStrategy","recordA","recordB","minProbabilityQuantifier","debug","debugData","extend","JSON","stringify","featuresA","extractFeatures","featuresB","featurePairs","generateFeaturePairs","similarityVector","generateSimilarityVector","some","v","probability","calculateprobability","returnResult","match","result","resultWithStrategy","formatStrategy","strategyNames","map","element","name","reduce","acc","record","extract","concat","value","compared","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}, returnStrategy = false) => (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\n debugData(`Strategy: ${JSON.stringify(strategy)}`);\n debugData(`Treshold: ${JSON.stringify(treshold)}`);\n debugData(`ReturnStrategy: ${JSON.stringify(returnStrategy)}`);\n\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 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 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() {\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,"sources":["../../src/match-detection/index.js"],"names":["strategy","treshold","returnStrategy","recordA","recordB","minProbabilityQuantifier","debug","debugData","extend","JSON","stringify","featuresA","extractFeatures","Array","isArray","recordsB","detectionResults","map","record","actualDetection","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","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\nexport default ({strategy, treshold = 0.9}, returnStrategy = false) => (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\n debugData(`Strategy: ${JSON.stringify(strategy)}`);\n debugData(`Treshold: ${JSON.stringify(treshold)}`);\n debugData(`ReturnStrategy: ${JSON.stringify(returnStrategy)}`);\n\n const featuresA = extractFeatures(recordA);\n\n debug(`We got an array of records: ${Array.isArray(recordB)}`);\n const recordsB = Array.isArray(recordB) ? recordB : [recordB];\n const detectionResults = recordsB.map(record => actualDetection(featuresA, record));\n\n return Array.isArray(recordB) ? detectionResults : detectionResults[0];\n\n function actualDetection(featuresA, record) {\n\n const featuresB = extractFeatures(record);\n\n debugData(`Features (a): ${JSON.stringify(featuresA)}`);\n debugData(`Features (b): ${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) {\n return strategy.reduce((acc, {name, extract}) => acc.concat({name, value: extract(record)}), []);\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"],"file":"index.js"}
@@ -12,6 +12,10 @@ var features = _interopRequireWildcard(require("./features"));
12
12
 
13
13
  var _ = _interopRequireDefault(require("."));
14
14
 
15
+ var _util = require("util");
16
+
17
+ var _debug = _interopRequireDefault(require("debug"));
18
+
15
19
  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
20
 
17
21
  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; }
@@ -45,6 +49,8 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
45
49
  * for the JavaScript code in this file.
46
50
  *
47
51
  */
52
+ const debug = (0, _debug.default)('@natlibfi/melinda-record-matching:match-detection:test');
53
+ const debugData = debug.extend('data');
48
54
  describe('match-detection', () => {
49
55
  (0, _fixugen.default)({
50
56
  path: [__dirname, '..', '..', 'test-fixtures', 'match-detection', 'index'],
@@ -57,16 +63,28 @@ describe('match-detection', () => {
57
63
  getFixture,
58
64
  options,
59
65
  expectedResults,
66
+ array,
60
67
  enabled = true
61
68
  }) => {
62
69
  if (!enabled) {
70
+ debug(`*** DISABLED TEST! ***`);
63
71
  return;
64
72
  }
65
73
 
66
74
  const detect = (0, _.default)(formatOptions());
67
- const recordA = new _marcRecord.MarcRecord(getFixture('recordA.json'));
68
- const recordB = new _marcRecord.MarcRecord(getFixture('recordB.json'));
75
+ const recordA = new _marcRecord.MarcRecord(getFixture('recordA.json'), {
76
+ subfieldValues: false
77
+ });
78
+ debugData((0, _util.inspect)(recordA));
79
+ debug(`Our recordB is an array of records: ${array}`);
80
+ const recordB = array ? getFixture('recordB.json').map(recordJson => new _marcRecord.MarcRecord(recordJson, {
81
+ subfieldValues: false
82
+ })) : new _marcRecord.MarcRecord(getFixture('recordB.json'), {
83
+ subfieldValues: false
84
+ });
85
+ debugData((0, _util.inspect)(recordB));
69
86
  const results = detect(recordA, recordB);
87
+ debugData(`${JSON.stringify(results)}`);
70
88
  (0, _chai.expect)(results).to.eql(expectedResults);
71
89
 
72
90
  function formatOptions() {
@@ -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,"sources":["../../src/match-detection/index.spec.js"],"names":["debug","debugData","extend","describe","path","__dirname","useMetadataFile","recurse","fixura","reader","READERS","JSON","callback","getFixture","options","expectedResults","array","enabled","detect","formatOptions","recordA","MarcRecord","subfieldValues","recordB","map","recordJson","results","stringify","to","eql","contextFeatures","features","strategy","type","v"],"mappings":";;AA4BA;;AACA;;AACA;;AACA;;AACA;;AACA;;AACA;;AACA;;;;;;;;AAnCA;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,MAAMA,KAAK,GAAG,oBAAkB,wDAAlB,CAAd;AACA,MAAMC,SAAS,GAAGD,KAAK,CAACE,MAAN,CAAa,MAAb,CAAlB;AAEAC,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,KAAvC;AAA8CC,MAAAA,OAAO,GAAG;AAAxD,KAAD,KAAmE;AAE3E,UAAI,CAACA,OAAL,EAAc;AACZjB,QAAAA,KAAK,CAAE,wBAAF,CAAL;AACA;AACD;;AAED,YAAMkB,MAAM,GAAG,eAAyBC,aAAa,EAAtC,CAAf;AACA,YAAMC,OAAO,GAAG,IAAIC,sBAAJ,CAAeR,UAAU,CAAC,cAAD,CAAzB,EAA2C;AAACS,QAAAA,cAAc,EAAE;AAAjB,OAA3C,CAAhB;AACArB,MAAAA,SAAS,CAAC,mBAAQmB,OAAR,CAAD,CAAT;AAEApB,MAAAA,KAAK,CAAE,uCAAsCgB,KAAM,EAA9C,CAAL;AACA,YAAMO,OAAO,GAAGP,KAAK,GACjBH,UAAU,CAAC,cAAD,CAAV,CAA2BW,GAA3B,CAA+BC,UAAU,IAAI,IAAIJ,sBAAJ,CAAeI,UAAf,EAA2B;AAACH,QAAAA,cAAc,EAAE;AAAjB,OAA3B,CAA7C,CADiB,GAEjB,IAAID,sBAAJ,CAAeR,UAAU,CAAC,cAAD,CAAzB,EAA2C;AAACS,QAAAA,cAAc,EAAE;AAAjB,OAA3C,CAFJ;AAGArB,MAAAA,SAAS,CAAC,mBAAQsB,OAAR,CAAD,CAAT;AAEA,YAAMG,OAAO,GAAGR,MAAM,CAACE,OAAD,EAAUG,OAAV,CAAtB;AACAtB,MAAAA,SAAS,CAAE,GAAEU,IAAI,CAACgB,SAAL,CAAeD,OAAf,CAAwB,EAA5B,CAAT;AAEA,wBAAOA,OAAP,EAAgBE,EAAhB,CAAmBC,GAAnB,CAAuBd,eAAvB;;AAEA,eAASI,aAAT,GAAyB;AACvB,cAAMW,eAAe,GAAGC,QAAQ,CAACjB,OAAO,CAACkB,QAAR,CAAiBC,IAAlB,CAAhC;AAEA,eAAO,EACL,GAAGnB,OADE;AAELkB,UAAAA,QAAQ,EAAElB,OAAO,CAACkB,QAAR,CAAiBD,QAAjB,CAA0BP,GAA1B,CAA8BU,CAAC,IAAIJ,eAAe,CAACI,CAAD,CAAf,EAAnC;AAFL,SAAP;AAID;AACF;AArCW,GAAd;AAuCD,CAxCO,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 '.';\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"],"file":"index.spec.js"}
@@ -64,7 +64,7 @@ function getMelindaIdsF035(record) {
64
64
  const melindaIdRegExp = /^(?<prefix>\(FI-MELINDA\)|FCC)(?<id>\d{9})$/u;
65
65
  return subfields.filter(sub => ['a', 'z'].includes(sub.code)).filter(sub => melindaIdRegExp.test(sub.value)).map(({
66
66
  value
67
- }) => value.replace(melindaIdRegExp, '$<id>'));
67
+ }) => value ? value.replace(melindaIdRegExp, '$<id>') : '');
68
68
  }
69
69
  }
70
70
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/matching-utils.js"],"names":["debug","debugData","extend","getMelindaIdsF035","record","f035s","getFields","length","allF035MelindaIds","concat","map","toMelindaIds","f035MelindaIds","Set","JSON","stringify","subfields","melindaIdRegExp","filter","sub","includes","code","test","value","replace","validateSidFieldSubfieldCounts","field","countC","countSubfields","countB","subfieldCode","getSubfieldValues"],"mappings":"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","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';\n\nconst debug = createDebugLogger('@natlibfi/melinda-record-matching:utils');\nconst debugData = debug.extend('data');\n\n// eslint-disable-next-line max-statements\nexport function getMelindaIdsF035(record) {\n\n const debug = createDebugLogger('@natlibfi/melinda-record-matching:melinda-id');\n const debugData = debug.extend('data');\n\n const f035s = record.getFields('035');\n\n if (f035s.length < 1) {\n debug(`No f035s found.`);\n return [];\n }\n\n const allF035MelindaIds = [].concat(...f035s.map(toMelindaIds));\n const f035MelindaIds = [...new Set(allF035MelindaIds)];\n\n debugData(`Fields (${f035s.length}): ${JSON.stringify(f035s)}`);\n debugData(`Ids (${allF035MelindaIds.length}): ${JSON.stringify(allF035MelindaIds)}`);\n debugData(`Unique ids (${f035MelindaIds.length}): ${JSON.stringify(f035MelindaIds)}`);\n\n return f035MelindaIds;\n\n function toMelindaIds({subfields}) {\n const melindaIdRegExp = /^(?<prefix>\\(FI-MELINDA\\)|FCC)(?<id>\\d{9})$/u;\n\n return subfields\n .filter(sub => ['a', 'z'].includes(sub.code))\n .filter(sub => melindaIdRegExp.test(sub.value))\n .map(({value}) => value.replace(melindaIdRegExp, '$<id>'));\n\n }\n}\n\nexport function validateSidFieldSubfieldCounts(field) {\n // Valid SID-fields have just one $c and one $b\n debugData(`Validating SID field ${JSON.stringify(field)}`);\n const countC = countSubfields(field, 'c');\n const countB = countSubfields(field, 'b');\n debug(`Found ${countC} sf $cs and ${countB} sf $bs. IsValid: ${countC === 1 && countB === 1}`);\n\n return countC === 1 && countB === 1;\n}\n\nfunction countSubfields(field, subfieldCode) {\n // debug(`Counting subfields ${subfieldCode}`);\n return field.subfields.filter(({code}) => code === subfieldCode).length;\n}\n\nexport function getSubfieldValues(field, subfieldCode) {\n debugData(`Get subfield(s) $${subfieldCode} from ${JSON.stringify(field)}`);\n return field.subfields.filter(({code}) => code === subfieldCode).map(({value}) => value);\n}\n\n"],"file":"matching-utils.js"}
1
+ {"version":3,"sources":["../src/matching-utils.js"],"names":["debug","debugData","extend","getMelindaIdsF035","record","f035s","getFields","length","allF035MelindaIds","concat","map","toMelindaIds","f035MelindaIds","Set","JSON","stringify","subfields","melindaIdRegExp","filter","sub","includes","code","test","value","replace","validateSidFieldSubfieldCounts","field","countC","countSubfields","countB","subfieldCode","getSubfieldValues"],"mappings":"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","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';\n\nconst debug = createDebugLogger('@natlibfi/melinda-record-matching:utils');\nconst debugData = debug.extend('data');\n\n// eslint-disable-next-line max-statements\nexport function getMelindaIdsF035(record) {\n\n const debug = createDebugLogger('@natlibfi/melinda-record-matching:melinda-id');\n const debugData = debug.extend('data');\n\n const f035s = record.getFields('035');\n\n if (f035s.length < 1) {\n debug(`No f035s found.`);\n return [];\n }\n\n const allF035MelindaIds = [].concat(...f035s.map(toMelindaIds));\n const f035MelindaIds = [...new Set(allF035MelindaIds)];\n\n debugData(`Fields (${f035s.length}): ${JSON.stringify(f035s)}`);\n debugData(`Ids (${allF035MelindaIds.length}): ${JSON.stringify(allF035MelindaIds)}`);\n debugData(`Unique ids (${f035MelindaIds.length}): ${JSON.stringify(f035MelindaIds)}`);\n\n return f035MelindaIds;\n\n function toMelindaIds({subfields}) {\n const melindaIdRegExp = /^(?<prefix>\\(FI-MELINDA\\)|FCC)(?<id>\\d{9})$/u;\n\n return subfields\n .filter(sub => ['a', 'z'].includes(sub.code))\n .filter(sub => melindaIdRegExp.test(sub.value))\n .map(({value}) => value ? value.replace(melindaIdRegExp, '$<id>') : '');\n\n }\n}\n\nexport function validateSidFieldSubfieldCounts(field) {\n // Valid SID-fields have just one $c and one $b\n debugData(`Validating SID field ${JSON.stringify(field)}`);\n const countC = countSubfields(field, 'c');\n const countB = countSubfields(field, 'b');\n debug(`Found ${countC} sf $cs and ${countB} sf $bs. IsValid: ${countC === 1 && countB === 1}`);\n\n return countC === 1 && countB === 1;\n}\n\nfunction countSubfields(field, subfieldCode) {\n // debug(`Counting subfields ${subfieldCode}`);\n return field.subfields.filter(({code}) => code === subfieldCode).length;\n}\n\nexport function getSubfieldValues(field, subfieldCode) {\n debugData(`Get subfield(s) $${subfieldCode} from ${JSON.stringify(field)}`);\n return field.subfields.filter(({code}) => code === subfieldCode).map(({value}) => value);\n}\n\n"],"file":"matching-utils.js"}
package/package.json CHANGED
@@ -14,7 +14,7 @@
14
14
  "url": "git@github.com:natlibfi/melinda-record-matching-js.git"
15
15
  },
16
16
  "license": "LGPL-3.0+",
17
- "version": "2.2.0-alpha.2",
17
+ "version": "2.2.0-alpha.3",
18
18
  "main": "./dist/index.js",
19
19
  "engines": {
20
20
  "node": ">=14"
@@ -66,6 +66,9 @@ export default ({record, searchSpec, url, maxCandidates, maxRecordsPerRequest =
66
66
 
67
67
  debug(`Searching matches for ${inputRecordId}`);
68
68
  debug(`Generated queryList ${JSON.stringify(queryList)}`);
69
+
70
+ // if generateQueryList errored we should throw 422
71
+
69
72
  if (queryList.length === 0) { // eslint-disable-line functional/no-conditional-statement
70
73
  throw new CandidateSearchError(`Generated query list contains no queries`);
71
74
  }
@@ -108,7 +108,7 @@ export function bibSourceIds(record) {
108
108
 
109
109
  function removeSourcePrefix(subfieldValue) {
110
110
  const sourcePrefixRegex = (/^(?<sourcePrefix>\([A-Za-z0-9-]+\))(?<id>.+)$/u);
111
- const normalizedValue = subfieldValue.replace(sourcePrefixRegex, '$<id>');
111
+ const normalizedValue = subfieldValue ? subfieldValue.replace(sourcePrefixRegex, '$<id>') : '';
112
112
  debugData(`Normalized ${subfieldValue} to ${normalizedValue}`);
113
113
  return normalizedValue;
114
114
  }
@@ -116,7 +116,7 @@ export function bibSourceIds(record) {
116
116
  function normalizeSidSubfieldValue(subfieldValue) {
117
117
  debugData(`Normalizing ${subfieldValue}`);
118
118
  const normalizeAwayRegex = (/[- ]/u);
119
- return subfieldValue.replace(normalizeAwayRegex, '');
119
+ return subfieldValue ? subfieldValue.replace(normalizeAwayRegex, '') : '';
120
120
  }
121
121
 
122
122
  }