From f0d697873e26931b0dc89976db9d826b8fc51811 Mon Sep 17 00:00:00 2001 From: Esko Ikkala <esko.ikkala@aalto.fi> Date: Tue, 11 Sep 2018 12:16:32 +0300 Subject: [PATCH] Add object mapper for SPARQL results --- src/client/containers/MapApp.js | 5 +- src/server/Datasets.js | 31 +++++---- src/server/SparqlObjectMapper.js | 114 +++++++++++++++++++++++++++++++ src/server/SparqlSearchEngine.js | 6 +- 4 files changed, 138 insertions(+), 18 deletions(-) create mode 100644 src/server/SparqlObjectMapper.js diff --git a/src/client/containers/MapApp.js b/src/client/containers/MapApp.js index 9c90da54..205287fd 100644 --- a/src/client/containers/MapApp.js +++ b/src/client/containers/MapApp.js @@ -135,6 +135,7 @@ let MapApp = (props) => { // console.log('oneColumnView', oneColumnView) // console.log('resultFormat', resultFormat) // console.log('mapMode', mapMode) + console.log(props.results) let table = ''; if ((oneColumnView && options.resultFormat === 'table') || (!oneColumnView)) { @@ -173,7 +174,6 @@ let MapApp = (props) => { /> ); } else { - console.log(props.results) mapElement = ( <LeafletMap results={props.results} @@ -267,7 +267,8 @@ const mapStateToProps = (state) => { browser: state.browser, search: state.search, map: state.map, - results: getVisibleResults(state.search), + // results: getVisibleResults(state.search), + results: state.search.results, resultValues: getVisibleValues(state.search), }; }; diff --git a/src/server/Datasets.js b/src/server/Datasets.js index 78d13e58..e682d709 100644 --- a/src/server/Datasets.js +++ b/src/server/Datasets.js @@ -17,36 +17,39 @@ module.exports = { PREFIX mmm-schema: <http://ldf.fi/mmm/schema/> PREFIX skos: <http://www.w3.org/2004/02/skos/core#> PREFIX sdbm: <https://sdbm.library.upenn.edu/> - SELECT ?id ?label ?sdbm_id ?material ?author ?timespan ?place ?lat ?long ?language { + SELECT * WHERE { ?id a frbroo:F4_Manifestation_Singleton . ?id rdfs:label ?label . ?id crm:P1_is_identified_by ?sdbm_id . OPTIONAL { - ?id crm:P45_consists_of ?material . + ?id crm:P45_consists_of ?material__id . + BIND (?material__id AS ?material__label) } ?expression_creation frbroo:R18_created ?id . OPTIONAL { - ?expression_creation crm:P14_carried_out_by ?author_id . - ?author_id skos:prefLabel ?author . - OPTIONAL { ?author_id mmm-schema:person_place/skos:prefLabel ?author_place . } + ?expression_creation crm:P14_carried_out_by ?author . + ?author skos:prefLabel ?author__label . + OPTIONAL { ?author mmm-schema:person_place/skos:prefLabel ?author__place . } } OPTIONAL { - ?expression_creation crm:P4_has_time_span ?timespan_id . - ?timespan_id rdfs:label ?timespan . - ?timespan crm:P79_beginning_is_qualified_by ?timespan_start . - ?timespan crm:P80_end_is_qualified_by ?timespan_end . + ?expression_creation crm:P4_has_time_span ?timespan . + ?timespan rdfs:label ?timespan__id . + ?timespan crm:P79_beginning_is_qualified_by ?timespan__start . + ?timespan crm:P80_end_is_qualified_by ?timespan__end . + BIND (?timespan__id AS ?timespan__label) } OPTIONAL { - ?expression_creation crm:P7_took_place_at ?place_id . - ?place_id skos:prefLabel ?place . + ?expression_creation crm:P7_took_place_at ?creation_place . + ?creation_place skos:prefLabel ?creation_place__id . OPTIONAL { - ?place_id wgs84:lat ?lat . - ?place_id wgs84:long ?long . + ?creation_place wgs84:lat ?creation_place__lat . + ?creation_place wgs84:long ?creation_place__long . } } OPTIONAL { ?id crm:P128_carries ?expression . - ?expression crm:P72_has_language ?language . + ?expression crm:P72_has_language ?language__id . + BIND (?language__id AS ?language__label) } } LIMIT 5000 diff --git a/src/server/SparqlObjectMapper.js b/src/server/SparqlObjectMapper.js new file mode 100644 index 00000000..a04da4d0 --- /dev/null +++ b/src/server/SparqlObjectMapper.js @@ -0,0 +1,114 @@ +import _ from 'lodash'; + +/** +* @param {Array} objects A list of objects as SPARQL results. +* @returns {Array} The mapped object list. +* @description +* Map the SPARQL results as objects, and return a list where result rows with the same +* id are merged into one object. +*/ +export const makeObjectList = (objects) => { + let objList = _.transform(objects, function(result, obj) { + if (!obj.id) { + return null; + } + //let orig = obj; + obj = makeObject(obj); + //obj = reviseObject(obj, orig); + mergeValueToList(result, obj); + }); + return objList; + //return self.postProcess(objList); +}; + +/** +* @param {Object} obj A single SPARQL result row object. +* @returns {Object} The mapped object. +* @description +* Flatten the result object. Discard everything except values. +* Assume that each property of the obj has a value property with +* the actual value. +*/ +const makeObject = (obj) => { + let o = new Object; + _.forIn(obj, function(value, key) { + // If the variable name contains "__", an object + // will be created as the value + // E.g. { place__id: '1' } -> { place: { id: '1' } } + _.set(o, key.replace(/__/g, '.'), value.value); + }); + return o; +}; + +/** +* @param {Array} valueList A list to which the value should be added. +* @param {Object} value The value to add to the list. +* @returns {Array} The merged list. +* @description +* Add the given value to the given list, merging an object value to and +* object in the list if both have the same id attribute. +* A value already present in valueList is discarded. +*/ +const mergeValueToList = (valueList, value) => { + let old; + if (_.isObject(value) && value.id) { + // Check if this object has been constructed earlier + old = _.findLast(valueList, function(e) { + return e.id === value.id; + }); + if (old) { + // Merge this object to the object constructed earlier + mergeObjects(old, value); + } + } else { + // Check if this value is present in the list + old = _.findLast(valueList, function(e) { + return _.isEqual(e, value); + }); + } + if (!old) { + // This is a distinct value + valueList.push(value); + } + return valueList; +}; + +/** +* @param {Object} first An object as returned by makeObject. +* @param {Object} second The object to merge with the first. +* @returns {Object} The merged object. +* @description +* Merges two objects. +*/ +const mergeObjects = (first, second) => { + // Merge two objects into one object. + return _.mergeWith(first, second, merger); +}; + +const merger = (a, b) => { + if (_.isEqual(a, b)) { + return a; + } + if (a && !b) { + return a; + } + if (b && !a) { + return b; + } + if (_.isArray(a)) { + if (_.isArray(b)) { + b.forEach(function(bVal) { + return mergeValueToList(a, bVal); + }); + return a; + } + return mergeValueToList(a, b); + } + if (_.isArray(b)) { + return mergeValueToList(b, a); + } + if (!(_.isObject(a) && _.isObject(b) && a.id === b.id)) { + return [a, b]; + } + return mergeObjects(a, b); +}; diff --git a/src/server/SparqlSearchEngine.js b/src/server/SparqlSearchEngine.js index d0d629b6..7fd96ee3 100644 --- a/src/server/SparqlSearchEngine.js +++ b/src/server/SparqlSearchEngine.js @@ -4,6 +4,7 @@ import { mapAllResults, mergeAllResults } from './Mappers'; +import { makeObjectList } from './SparqlObjectMapper'; class SparqlSearchEngine { @@ -13,6 +14,7 @@ class SparqlSearchEngine { if (data.results.bindings.length === 0) { return []; } + console.log(data.results.bindings) return mapper ? mapper(data.results.bindings) : data.results.bindings; }); } @@ -20,8 +22,8 @@ class SparqlSearchEngine { getAllManuscripts(datasetId) { const { endpoint, getAllQuery } = datasetConfig[datasetId]; const sparqlApi = new SparqlApi({ endpoint }); - console.log(getAllQuery) - return this.doSearch(getAllQuery, sparqlApi, mapAllResults); + //console.log(getAllQuery) + return this.doSearch(getAllQuery, sparqlApi, makeObjectList); } getFederatedManuscripts(datasets) { -- GitLab