Skip to content
This repository has been archived by the owner on Jun 22, 2023. It is now read-only.

Improve JSON-LD output for itemlists #207

Merged
merged 6 commits into from
Jul 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions src/routes/helpers/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { driver } from '../../driver'
import GetTypeQuery from '../../queries/GetTypeQuery'
import GetFullNodeQuery from '../../queries/GetFullNodeQuery'
import SchemaHelper from '../../helpers/SchemaHelper'
import fs from 'fs'
import path from 'path'

export const getDocument = (identifier, host) => {
const session = driver.session()
Expand Down Expand Up @@ -30,6 +32,15 @@ export const getDocument = (identifier, host) => {
return Promise.reject(new Error('Node not found'))
}

// Special-case some types to perform a custom query to get additional relations in a single query
// Unfortunately neo4j-graphql-js doesn't provide an easy way to do this, so we do the following:
// Start up the CE with DEBUG=neo4j-graphql-js
// Take the file ./queries/TYPE.query and run it in the web interface
// Copy the query which is written to the console to ./queries/TYPE.cypher
if (type === "ItemList") {
return getItemList(session, identifier).then(data => ({data, type}));
}

return getNodeProperties(session, type, identifier, host)
.then(data => ({ data, type }))
}, reason => {
Expand All @@ -41,6 +52,62 @@ export const getDocument = (identifier, host) => {
})
}

const getItemList = (session, identifier) => {
const query = fs.readFileSync(path.resolve(__dirname, './queries/ItemList.cypher'), {encoding:'utf8', flag:'r'});
return session.run(query, {identifier: identifier, ThingInterface_derivedTypes: [
"Action",
"AddAction",
"Annotation",
"Article",
"Audience",
"AudioObject",
"ControlAction",
"DataDownload",
"Dataset",
"DefinedTerm",
"DefinedTermSet",
"DeleteAction",
"DigitalDocument",
"DigitalDocumentPermission",
"EntryPoint",
"Event",
"ImageObject",
"Intangible",
"ItemList",
"ListItem",
"MediaObject",
"MusicAlbum",
"MusicComposition",
"MusicGroup",
"MusicPlaylist",
"MusicRecording",
"Occupation",
"Organization",
"Person",
"Place",
"Product",
"Property",
"PropertyValue",
"PropertyValueSpecification",
"Rating",
"ReplaceAction",
"Review",
"SoftwareApplication",
"VideoObject"
]})
.then(fullResult => {
if (fullResult.records.length) {
return fullResult.records[0].get('itemList')
} else {
return undefined;
}
})
.catch(function (error) {
info('_getItemList caught error: ' + error.message)
throw error
})
}

const getNodeProperties = (session, type, identifier, host) => {
const getFullNodeQuery = new GetFullNodeQuery(type, identifier, host, 2)
const query = getFullNodeQuery.query
Expand Down
3 changes: 0 additions & 3 deletions src/routes/helpers/jsonld/DefinedTerm.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,6 @@
],
"inDefinedTermSet": [
"https://pending.schema.org/inDefinedTermSet"
],
"broader": [
"http://www.w3.org/2004/02/skos/core#broader"
]
}
}
6 changes: 6 additions & 0 deletions src/routes/helpers/jsonld/DefinedTermSet.json
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,12 @@
],
"hasDefinedTerm": [
"https://pending.schema.org/hasDefinedTerm"
],
"broaderUrl": [
"http://www.w3.org/2004/02/skos/core#broader"
],
"broaderMotivation": [
"http://www.w3.org/2004/02/skos/core#broader"
]
}
}
1 change: 1 addition & 0 deletions src/routes/helpers/jsonld/ItemList.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"http://www.w3.org/ns/ldp#BasicContainer"
]
},
"nonRelationalProperties": ["itemListElement"],
"properties": {
"identifier": [
"http://purl.org/dc/terms/identifier",
Expand Down
2 changes: 1 addition & 1 deletion src/routes/helpers/jsonld/ListItem.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"https://schema.org/ListItem"
]
},
"relationalProperties": ["itemUrl"],
"relationalProperties": ["itemUrl", "item"],
"properties": {
"identifier": [
"http://purl.org/dc/terms/identifier",
Expand Down
1 change: 1 addition & 0 deletions src/routes/helpers/queries/ItemList.cypher
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
MATCH (`itemList`:`ItemList` {identifier:$identifier}) RETURN `itemList` { .identifier , .name , .creator ,created: { formatted: toString(`itemList`.created) },modified: { formatted: toString(`itemList`.modified) }, .additionalType , .itemListOrder ,itemListElement: [(`itemList`)-[:`ITEM_LIST_ELEMENT`]->(`itemList_itemListElement`:`ThingInterface`) WHERE ("Action" IN labels(`itemList_itemListElement`) OR "AddAction" IN labels(`itemList_itemListElement`) OR "Annotation" IN labels(`itemList_itemListElement`) OR "Article" IN labels(`itemList_itemListElement`) OR "Audience" IN labels(`itemList_itemListElement`) OR "AudioObject" IN labels(`itemList_itemListElement`) OR "ControlAction" IN labels(`itemList_itemListElement`) OR "DataDownload" IN labels(`itemList_itemListElement`) OR "Dataset" IN labels(`itemList_itemListElement`) OR "DefinedTerm" IN labels(`itemList_itemListElement`) OR "DefinedTermSet" IN labels(`itemList_itemListElement`) OR "DeleteAction" IN labels(`itemList_itemListElement`) OR "DigitalDocument" IN labels(`itemList_itemListElement`) OR "DigitalDocumentPermission" IN labels(`itemList_itemListElement`) OR "EntryPoint" IN labels(`itemList_itemListElement`) OR "Event" IN labels(`itemList_itemListElement`) OR "ImageObject" IN labels(`itemList_itemListElement`) OR "Intangible" IN labels(`itemList_itemListElement`) OR "ItemList" IN labels(`itemList_itemListElement`) OR "ListItem" IN labels(`itemList_itemListElement`) OR "MediaObject" IN labels(`itemList_itemListElement`) OR "MusicAlbum" IN labels(`itemList_itemListElement`) OR "MusicComposition" IN labels(`itemList_itemListElement`) OR "MusicGroup" IN labels(`itemList_itemListElement`) OR "MusicPlaylist" IN labels(`itemList_itemListElement`) OR "MusicRecording" IN labels(`itemList_itemListElement`) OR "Occupation" IN labels(`itemList_itemListElement`) OR "Organization" IN labels(`itemList_itemListElement`) OR "Person" IN labels(`itemList_itemListElement`) OR "Place" IN labels(`itemList_itemListElement`) OR "Product" IN labels(`itemList_itemListElement`) OR "Property" IN labels(`itemList_itemListElement`) OR "PropertyValue" IN labels(`itemList_itemListElement`) OR "PropertyValueSpecification" IN labels(`itemList_itemListElement`) OR "Rating" IN labels(`itemList_itemListElement`) OR "ReplaceAction" IN labels(`itemList_itemListElement`) OR "Review" IN labels(`itemList_itemListElement`) OR "SoftwareApplication" IN labels(`itemList_itemListElement`) OR "VideoObject" IN labels(`itemList_itemListElement`)) | head([`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "Action" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "Action", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "AddAction" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "AddAction", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "Annotation" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "Annotation", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "Article" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "Article", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "Audience" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "Audience", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "AudioObject" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "AudioObject", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "ControlAction" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "ControlAction", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "DataDownload" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "DataDownload", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "Dataset" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "Dataset", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "DefinedTerm" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "DefinedTerm", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "DefinedTermSet" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "DefinedTermSet", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "DeleteAction" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "DeleteAction", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "DigitalDocument" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "DigitalDocument", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "DigitalDocumentPermission" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "DigitalDocumentPermission", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "EntryPoint" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "EntryPoint", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "Event" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "Event", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "ImageObject" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "ImageObject", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "Intangible" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "Intangible", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "ItemList" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "ItemList", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "ListItem" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "ListItem", .itemUrl ,item: [(`itemList_itemListElement`)-[:`ITEM`]->(`itemList_itemListElement_item`:`ThingInterface`) | `itemList_itemListElement_item` {FRAGMENT_TYPE: head( [ label IN labels(`itemList_itemListElement_item`) WHERE label IN $ThingInterface_derivedTypes ] ), .identifier }] , .position , .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "MediaObject" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "MediaObject", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "MusicAlbum" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "MusicAlbum", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "MusicComposition" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "MusicComposition", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "MusicGroup" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "MusicGroup", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "MusicPlaylist" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "MusicPlaylist", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "MusicRecording" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "MusicRecording", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "Occupation" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "Occupation", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "Organization" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "Organization", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "Person" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "Person", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "Place" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "Place", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "Product" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "Product", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "Property" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "Property", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "PropertyValue" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "PropertyValue", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "PropertyValueSpecification" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "PropertyValueSpecification", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "Rating" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "Rating", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "ReplaceAction" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "ReplaceAction", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "Review" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "Review", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "SoftwareApplication" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "SoftwareApplication", .identifier , .name , .description , .image , .url }] + [`itemList_itemListElement` IN [`itemList_itemListElement`] WHERE "VideoObject" IN labels(`itemList_itemListElement`) | `itemList_itemListElement` { FRAGMENT_TYPE: "VideoObject", .identifier , .name , .description , .image , .url }])] } AS `itemList`
30 changes: 30 additions & 0 deletions src/routes/helpers/queries/ItemList.query
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
query {
ItemList(identifier:"a1a839c0-4b6b-49e3-ac11-384568ce0caf") {
identifier
name
creator
created {
formatted
}
modified {
formatted
}
itemListOrder
additionalType
itemListElement {
__typename
identifier
name
description
image
url
... on ListItem {
itemUrl
item {
identifier
}
position
}
}
}
}
46 changes: 46 additions & 0 deletions src/routes/helpers/testdata/itemlist.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"identifier": "a1a839c0-4b6b-49e3-ac11-384568ce0caf",
"creator": "https://testuser.trompa-solid.upf.edu/profile/card#me",
"itemListElement": [
{
"identifier": "bb418c6b-7667-4559-96de-5716d9d52e2e",
"image": null,
"item": [
{
"FRAGMENT_TYPE": "Annotation",
"identifier": "e03dd66d-17ba-4d91-a409-d1eb2cb3d3bb"
}
],
"name": null,
"description": null,
"FRAGMENT_TYPE": "ListItem",
"position": null,
"url": null,
"itemUrl": null
},
{
"identifier": "551877a6-c61b-4fc7-8174-17247d460823",
"image": null,
"item": null,
"name": null,
"description": null,
"FRAGMENT_TYPE": "ListItem",
"position": null,
"url": null,
"itemUrl": "https://example.com/externalItem"
},
{
"identifier": "f3ed1b21-cc30-43be-805a-ce2b56b78e09",
"name": null,
"description": null,
"FRAGMENT_TYPE": "DigitalDocument",
"image": null,
"url": null
}
],
"additionalType": [ "https://vocab.trompamusic.eu/vocab#AnnotationSession" ],
"created": { "formatted": "2021-06-22T13:47:10.693Z" },
"name": "Some session",
"modified": { "formatted": "2021-06-22T13:47:10.693Z" },
"itemListOrder": "ItemListUnordered"
}
Loading