diff --git a/.DS_Store b/.DS_Store index a1c56bf0..1cec5c2e 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/lib/response_massager.js b/lib/response_massager.js index a75aeb63..bf419a52 100644 --- a/lib/response_massager.js +++ b/lib/response_massager.js @@ -1,7 +1,7 @@ const LocationLabelUpdater = require('./location_label_updater') const AvailabilityResolver = require('./availability_resolver.js') const parallelFieldsExtractor = require('./parallel-fields-extractor') -const { isAeonUrl } = require('../lib/util') +const { isAeonUrl, sortOnPropWithUndefinedLast } = require('../lib/util') const FulfillmentResolver = require('./fulfillment_resolver') const RequestabilityResolver = require('./requestability_resolver') @@ -22,10 +22,10 @@ class ResponseMassager { processInnerHitsProperties (response, sortOnEnumerationChronology) { response.hits.hits.forEach((hit) => { if (sortOnEnumerationChronology) { - hit._source.items.sort((a, b) => a.enumerationChronology_sort[0] > b.enumerationChronology_sort[0] ? -1 : 1) + hit._source.items.sort(sortOnPropWithUndefinedLast('enumerationChronology_sort')) } // Process "items" inner_hits - if (hit.inner_hits && hit.inner_hits.items) { + if (hit?.inner_hits?.items) { // Reassign items inner_hits to .items hit._source.items = hit.inner_hits.items.hits.hits.map((itemHit) => itemHit._source) @@ -40,7 +40,7 @@ class ResponseMassager { hit._source.numItemsTotal = [unfilteredItems.hits.total] } // Process "electronicResources" inner_hits - if (hit.inner_hits && hit.inner_hits.electronicResources) { + if (hit?.inner_hits?.electronicResources) { // If record doesn't have indexed electronicResources... if (!hit._source.electronicResources || hit._source.electronicResources.length === 0) { // Gather up all records in the electronicResources inner_hit, diff --git a/lib/util.js b/lib/util.js index bc66108d..2cdbe1ba 100644 --- a/lib/util.js +++ b/lib/util.js @@ -1,6 +1,10 @@ const logger = require('./logger') const isItemNyplOwned = require('./ownership_determination').isItemNyplOwned +exports.sortOnPropWithUndefinedLast = (property) => { + return (a, b) => a[property]?.[0] || Number.MAX_SAFE_INTEGER > b[property]?.[0] || Number.MAX_SAFE_INTEGER ? -1 : 1 +} + exports.buildJsonLdContext = function (prefixes) { const context = JSON.parse(JSON.stringify(prefixes)) delete context.urn diff --git a/test/.DS_Store b/test/.DS_Store new file mode 100644 index 00000000..c7c45607 Binary files /dev/null and b/test/.DS_Store differ diff --git a/test/fixtures/mangled_enumerationChronology_items.json b/test/fixtures/mangled_enumerationChronology_items.json new file mode 100644 index 00000000..146bf12d --- /dev/null +++ b/test/fixtures/mangled_enumerationChronology_items.json @@ -0,0 +1,552 @@ +[{ + "uri": "i34504228", + "status": [ + { + "id": "status:a", + "label": "Available" + } + ], + "status_packed": [ + "status:a||Available" + ], + "owner": [ + { + "id": "orgs:1000", + "label": "Stephen A. Schwarzman Building" + } + ], + "owner_packed": [ + "orgs:1000||Stephen A. Schwarzman Building" + ], + "catalogItemType": [ + { + "id": "catalogItemType:6", + "label": "microfilm service copy" + } + ], + "catalogItemType_packed": [ + "catalogItemType:6||microfilm service copy" + ], + "holdingLocation": [ + { + "id": "loc:rcmi2", + "label": "Offsite" + } + ], + "holdingLocation_packed": [ + "loc:rcmi2||Offsite" + ], + "shelfMark": [ + "*ZY (Helsingin sanomat) Aug 1 216 - Aug 10 216" + ], + "identifierV2": [ + { + "value": "*ZY (Helsingin sanomat) Aug 1 216 - Aug 10 216", + "type": "bf:ShelfMark" + }, + { + "type": "bf:Barcode", + "value": "33433117677694" + } + ], + "enumerationChronology": [ + "Aug 1 216 - Aug 10 216" + ], + "physicalLocation": [ + "*ZY (Helsingin sanomat)" + ], + "recapCustomerCode": [ + "NA" + ], + "identifier": [ + "urn:barcode:33433117677694" + ], + "idBarcode": [ + "33433117677694" + ], + "requestable": [ + true + ], + "accessMessage": [ + { + "id": "accessMessage:2", + "label": "Request in advance" + } + ], + "accessMessage_packed": [ + "accessMessage:2||Request in advance" + ], + "type": [ + "bf:Item" + ], + "formatLiteral": [ + "Text" + ], + "shelfMark_sort": "a*ZY (Helsingin sanomat) Aug 1 216 - Aug 10 000216" +}, +{ + "uri": "i30662443", + "status": [ + { + "id": "status:a", + "label": "Available" + } + ], + "status_packed": [ + "status:a||Available" + ], + "owner": [ + { + "id": "orgs:1000", + "label": "Stephen A. Schwarzman Building" + } + ], + "owner_packed": [ + "orgs:1000||Stephen A. Schwarzman Building" + ], + "catalogItemType": [ + { + "id": "catalogItemType:6", + "label": "microfilm service copy" + } + ], + "catalogItemType_packed": [ + "catalogItemType:6||microfilm service copy" + ], + "holdingLocation": [ + { + "id": "loc:rcmi2", + "label": "Offsite" + } + ], + "holdingLocation_packed": [ + "loc:rcmi2||Offsite" + ], + "shelfMark": [ + "*ZY (Helsingin sanomat) Feb. 1-14, 19828" + ], + "identifierV2": [ + { + "value": "*ZY (Helsingin sanomat) Feb. 1-14, 19828", + "type": "bf:ShelfMark" + }, + { + "type": "bf:Barcode", + "value": "33433109747869" + } + ], + "enumerationChronology": [ + "Feb. 1-14, 19828" + ], + "physicalLocation": [ + "*ZY (Helsingin sanomat)" + ], + "recapCustomerCode": [ + "NA" + ], + "identifier": [ + "urn:barcode:33433109747869" + ], + "idBarcode": [ + "33433109747869" + ], + "requestable": [ + true + ], + "accessMessage": [ + { + "id": "accessMessage:2", + "label": "Request in advance" + } + ], + "accessMessage_packed": [ + "accessMessage:2||Request in advance" + ], + "type": [ + "bf:Item" + ], + "formatLiteral": [ + "Text" + ], + "shelfMark_sort": "a*ZY (Helsingin sanomat) Feb. 1-14, 019828" +}, +{ + "uri": "i16755735", + "status": [ + { + "id": "status:a", + "label": "Available" + } + ], + "status_packed": [ + "status:a||Available" + ], + "owner": [ + { + "id": "orgs:1000", + "label": "Stephen A. Schwarzman Building" + } + ], + "owner_packed": [ + "orgs:1000||Stephen A. Schwarzman Building" + ], + "catalogItemType": [ + { + "id": "catalogItemType:6", + "label": "microfilm service copy" + } + ], + "catalogItemType_packed": [ + "catalogItemType:6||microfilm service copy" + ], + "holdingLocation": [ + { + "id": "loc:rcmi2", + "label": "Offsite" + } + ], + "holdingLocation_packed": [ + "loc:rcmi2||Offsite" + ], + "shelfMark": [ + "*ZY (Helsingin sanomat) Feb 7 2007 - Feb 13 2007" + ], + "identifierV2": [ + { + "value": "*ZY (Helsingin sanomat) Feb 7 2007 - Feb 13 2007", + "type": "bf:ShelfMark" + }, + { + "type": "bf:Barcode", + "value": "33433074504451" + } + ], + "enumerationChronology": [ + "Feb 7 2007 - Feb 13 2007" + ], + "physicalLocation": [ + "*ZY (Helsingin sanomat)" + ], + "recapCustomerCode": [ + "NA" + ], + "identifier": [ + "urn:barcode:33433074504451" + ], + "idBarcode": [ + "33433074504451" + ], + "requestable": [ + true + ], + "accessMessage": [ + { + "id": "accessMessage:2", + "label": "Request in advance" + } + ], + "accessMessage_packed": [ + "accessMessage:2||Request in advance" + ], + "dateRange": [ + { + "gte": "2007", + "lte": "2007" + } + ], + "enumerationChronology_sort": [ + " -2007" + ], + "type": [ + "bf:Item" + ], + "formatLiteral": [ + "Text" + ], + "shelfMark_sort": "a*ZY (Helsingin sanomat) Feb 7 2007 - Feb 13 002007" +}, +{ + "uri": "i11184820", + "status": [ + { + "id": "status:a", + "label": "Available" + } + ], + "status_packed": [ + "status:a||Available" + ], + "owner": [ + { + "id": "orgs:1000", + "label": "Stephen A. Schwarzman Building" + } + ], + "owner_packed": [ + "orgs:1000||Stephen A. Schwarzman Building" + ], + "catalogItemType": [ + { + "id": "catalogItemType:6", + "label": "microfilm service copy" + } + ], + "catalogItemType_packed": [ + "catalogItemType:6||microfilm service copy" + ], + "holdingLocation": [ + { + "id": "loc:rcmi2", + "label": "Offsite" + } + ], + "holdingLocation_packed": [ + "loc:rcmi2||Offsite" + ], + "shelfMark": [ + "*ZY (Helsingin sanomat) Feb 8 2002 - Feb 14 2002" + ], + "identifierV2": [ + { + "value": "*ZY (Helsingin sanomat) Feb 8 2002 - Feb 14 2002", + "type": "bf:ShelfMark" + }, + { + "type": "bf:Barcode", + "value": "33433031402682" + } + ], + "enumerationChronology": [ + "Feb 8 2002 - Feb 14 2002" + ], + "physicalLocation": [ + "*ZY (Helsingin sanomat)" + ], + "recapCustomerCode": [ + "NA" + ], + "identifier": [ + "urn:barcode:33433031402682" + ], + "idBarcode": [ + "33433031402682" + ], + "requestable": [ + true + ], + "accessMessage": [ + { + "id": "accessMessage:2", + "label": "Request in advance" + } + ], + "accessMessage_packed": [ + "accessMessage:2||Request in advance" + ], + "dateRange": [ + { + "gte": "2002", + "lte": "2002" + } + ], + "enumerationChronology_sort": [ + " -2002" + ], + "type": [ + "bf:Item" + ], + "formatLiteral": [ + "Text" + ], + "shelfMark_sort": "a*ZY (Helsingin sanomat) Feb 8 2002 - Feb 14 002002" +}, +{ + "uri": "i30660665", + "status": [ + { + "id": "status:a", + "label": "Available" + } + ], + "status_packed": [ + "status:a||Available" + ], + "owner": [ + { + "id": "orgs:1000", + "label": "Stephen A. Schwarzman Building" + } + ], + "owner_packed": [ + "orgs:1000||Stephen A. Schwarzman Building" + ], + "catalogItemType": [ + { + "id": "catalogItemType:6", + "label": "microfilm service copy" + } + ], + "catalogItemType_packed": [ + "catalogItemType:6||microfilm service copy" + ], + "holdingLocation": [ + { + "id": "loc:rcmi2", + "label": "Offsite" + } + ], + "holdingLocation_packed": [ + "loc:rcmi2||Offsite" + ], + "shelfMark": [ + "*ZY (Helsingin sanomat) Sept. 1-15, 1979" + ], + "identifierV2": [ + { + "value": "*ZY (Helsingin sanomat) Sept. 1-15, 1979", + "type": "bf:ShelfMark" + }, + { + "type": "bf:Barcode", + "value": "33433109747257" + } + ], + "enumerationChronology": [ + "Sept. 1-15, 1979" + ], + "physicalLocation": [ + "*ZY (Helsingin sanomat)" + ], + "recapCustomerCode": [ + "NA" + ], + "identifier": [ + "urn:barcode:33433109747257" + ], + "idBarcode": [ + "33433109747257" + ], + "requestable": [ + true + ], + "accessMessage": [ + { + "id": "accessMessage:2", + "label": "Request in advance" + } + ], + "accessMessage_packed": [ + "accessMessage:2||Request in advance" + ], + "dateRange": [ + { + "gte": "1979", + "lte": "1979" + } + ], + "enumerationChronology_sort": [ + " -1979" + ], + "type": [ + "bf:Item" + ], + "formatLiteral": [ + "Text" + ], + "shelfMark_sort": "a*ZY (Helsingin sanomat) Sept. 1-15, 001979" +}, +{ + "uri": "i30651725", + "status": [ + { + "id": "status:a", + "label": "Available" + } + ], + "status_packed": [ + "status:a||Available" + ], + "owner": [ + { + "id": "orgs:1000", + "label": "Stephen A. Schwarzman Building" + } + ], + "owner_packed": [ + "orgs:1000||Stephen A. Schwarzman Building" + ], + "catalogItemType": [ + { + "id": "catalogItemType:6", + "label": "microfilm service copy" + } + ], + "catalogItemType_packed": [ + "catalogItemType:6||microfilm service copy" + ], + "holdingLocation": [ + { + "id": "loc:rcmi2", + "label": "Offsite" + } + ], + "holdingLocation_packed": [ + "loc:rcmi2||Offsite" + ], + "shelfMark": [ + "*ZY (Helsingin sanomat) Sept. 1-24, 1957" + ], + "identifierV2": [ + { + "value": "*ZY (Helsingin sanomat) Sept. 1-24, 1957", + "type": "bf:ShelfMark" + }, + { + "type": "bf:Barcode", + "value": "33433109767248" + } + ], + "enumerationChronology": [ + "Sept. 1-24, 1957" + ], + "physicalLocation": [ + "*ZY (Helsingin sanomat)" + ], + "recapCustomerCode": [ + "NA" + ], + "identifier": [ + "urn:barcode:33433109767248" + ], + "idBarcode": [ + "33433109767248" + ], + "requestable": [ + true + ], + "accessMessage": [ + { + "id": "accessMessage:2", + "label": "Request in advance" + } + ], + "accessMessage_packed": [ + "accessMessage:2||Request in advance" + ], + "dateRange": [ + { + "gte": "1957", + "lte": "1957" + } + ], + "enumerationChronology_sort": [ + " -1957" + ], + "type": [ + "bf:Item" + ], + "formatLiteral": [ + "Text" + ], + "shelfMark_sort": "a*ZY (Helsingin sanomat) Sept. 1-24, 001957" +}] \ No newline at end of file diff --git a/test/util.test.js b/test/util.test.js index c6a4ef71..8625ce0a 100644 --- a/test/util.test.js +++ b/test/util.test.js @@ -1,8 +1,24 @@ const { expect } = require('chai') +const mangledEnumerationChronologyItems = require('./fixtures/mangled_enumerationChronology_items.json') const util = require('../lib/util') describe('Util', function () { + describe.only('sortOnPropWithUndefinedLast', () => { + it('sorts undefined last', () => { + const sortedItemEnums = mangledEnumerationChronologyItems + .sort(util.sortOnPropWithUndefinedLast('enumerationChronology_sort')) + .map((item) => item.enumerationChronology) + expect(sortedItemEnums).to.deep.equal([ + ['Sept. 1-24, 1957'], + ['Sept. 1-15, 1979'], + ['Feb 8 2002 - Feb 14 2002'], + ['Feb 7 2007 - Feb 13 2007'], + ['Feb. 1-14, 19828'], + ['Aug 1 216 - Aug 10 216'] + ]) + }) + }) describe('backslashes', function () { it('escapes specials', function () { const result = util.backslashes('?', 2)