From df13fd97cb2b0f491b35940811f8396607e5d5e5 Mon Sep 17 00:00:00 2001 From: Dionysia Nakou Date: Fri, 30 Aug 2024 12:50:43 +0200 Subject: [PATCH 1/9] add api doc --- docs/triply-api/index.md | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/docs/triply-api/index.md b/docs/triply-api/index.md index 7231d684..844735a7 100644 --- a/docs/triply-api/index.md +++ b/docs/triply-api/index.md @@ -825,8 +825,45 @@ Result: ``` ## GraphQL + This endpoint can be used for GraphQL queries. It uses information from user-provided SHACL shapes for the schema creation. + +### URI path + +GraphQL requests are sent to the following URI path: + +```iri +https://api.INSTANCE/datasets/ACCOUNT/DATASET/graphql +``` + +### Requests and Response +The format of requests and the response expected are described by [graphql.org](https://graphql.org/learn/serving-over-http/) + + +### Example + + +Perform a search using the custom query: + +```json +{ + "query": { + "{ PersonConnection { edges { node { id name } } } }" + } +} +``` + +This request is issued in the following way with the cURL command-line tool: + +```sh + curl -X POST http://api./datasets///graphql + -d '{"query":"{ PersonConnection { edges { node { id name } } } }"}' + -H 'Content-Type: application/json' +``` + + ## Elasticsearch The text search API returns a list of linked data entities based on a supplied text string. The text string is matched against the text in literals and IRIs that appear in the linked data description of the returned entities. From 02fdf1edb2185721dd0380cb334325ab99e99e52 Mon Sep 17 00:00:00 2001 From: Dionysia Nakou Date: Mon, 2 Sep 2024 11:52:46 +0200 Subject: [PATCH 2/9] wip --- docs/generics/Graphql.md | 413 +++++++++++++++++++++++++++++++++++++++ docs/triply-api/index.md | 406 +------------------------------------- 2 files changed, 414 insertions(+), 405 deletions(-) create mode 100644 docs/generics/Graphql.md diff --git a/docs/generics/Graphql.md b/docs/generics/Graphql.md new file mode 100644 index 00000000..83dd545c --- /dev/null +++ b/docs/generics/Graphql.md @@ -0,0 +1,413 @@ +--- +title: "GraphQL endpoint" +path: "/docs/graphql" +--- + +[TOC] + +# Graphql endpoint +TriplyDB exposes a GraphQL endpoint. This endpoint uses information from user-provided SHACL shapes for the schema creation. + +The goal of this documentation is to inform users about Triply's implementation of the GraphQL endpoint. For more generic information about GraphQL, you can visit [graphql.org](https://graphql.org/) or other resources. In order to understand this documentation, you have to be familiar with the SHACL language. + +### Schema +#### Object types +A basic element of the schema is object types, which represents the type of the objects that you can query. + +```graphql +type Book { + id:ID! + title:[XsdString]! +} +``` +This object type corresponds to the shape below: + +```turtle +shp:Book a sh:NodeShape; + sh:targetClass sdo:Book; + sh:property [ + sh:path dc:title; + sh:datatype xsd:string.] +``` +#### Fields +Fields in object types, such as `title`, represent properties of nodes. By default, fields return arrays of values. The only exception is when the property has `sh:maxCount: 1`, then the field returns a single value. +Thus, for the shape: +```turtle +shp:Book a sh:NodeShape; + sh:targetClass sdo:Book; + sh:property [ + sh:path dc:title; + sh:maxCount "1"^^xsd:integer; + sh:datatype xsd:string.] +``` + +The object type will be: +```graphql +type Book { + id:ID! + title:XsdString +} +``` +Additionally, following the [best practices](https://graphql.org/learn/best-practices/#nullability), fields can give null results, except for: + +- IDs, which represents the IRI of the resource. +- Lists, but not their elements +- Properties that have `sh:minCount 1` and `sh:maxCount 1` + +Thus, for this shape: +```turtle +shp:Book a sh:NodeShape; + sh:targetClass sdo:Book; + sh:property [ + sh:path dc:title; + sh:maxCount "1"^^xsd:integer; + sh:minCount "1"^^xsd:integer; + sh:datatype xsd:string.] +``` +The corresponding object type is: +```graphql +type Book { + id:ID! + title:XsdString! +} +``` + + +If the property shape includes an `sh:datatype`, the field returns values of GraphQL scalar type (see example above). On the other hand, if the property shape has an `sh:class` pointing to a class that: +- is the `sh:targetClass` of a node shape, the field returns values of the corresponding object type. +- is not mentioned as a `sh:targetClass` in a node shape, then the type of the returned values is `ExternalIri`. + +Therefore, the shapes : +```turtle +shp:Book a sh:NodeShape; + sh:targetClass sdo:Book; + sh:property [ + sh:path sdo:author; + sh:class sdo:Person.]; + sh:property [ + sh:path sdo:audio; + sh:class sdo:AudioObject.]. + + +shp:Person a sh:NodeShape; + sh:targetClass sdo:Person; + sh:property [ + sh:path sdo:name; + sh:datatype xsd:string.]. +``` +correspond to the below graphql types: +```graphql +type Book { + id:ID! + author:[Person]! + audio:[ExternalIri]! +} + +type Person { + id:ID! + name:[XsdString]! +} +``` +#### IDs +The id field is of type ID, which represents the IRI of each object. This ID is unique. +For example: +```turtle +book:Odyssey a sdo:Book; + dc:title "Odyssey". +``` +The id field of this resource would be `https://example.org/book/Odyssey`. +You can read more information on the `ID` scalar in [graphql.org](https://graphql.org/learn/schema/#scalar-types). Also, the use of the `id` field is mentioned later in the section [Object Global Identification](#global-object-identification). + +#### Naming +In order to name the GraphQL types in correspondence to shapes, we follow the below conventions: +- For object types, we use the `sh:targetClass` of the node shape. +- For object type fields, we use the `sh:path` of the property shape. + +More specifically, the name comes from the part of the IRI after the last `#` or otherwise the last `/`, converted from kebab-case to camelCase. + +Notice that if the selected name is illegal or causes a name collision, we'll return an error informing the user about the problem and ignore this type or field. + + ##### Renaming + Shape designers are able use their custom names by using a special property: ``. + More specifically, the designer has to add a triple with : + - for object types, the class IRI + - for fields, the IRI of the property shape + +as a subject, the above-mentioned predicate and a string literal with the custom name as object. + + If we wanted to rename using the first example of the section, we would do: +```turtle +shp:Book a sh:NodeShape; + sh:targetClass sdo:Book; + sh:property [ + sh:path dc:title; + triply:graphqlName "name" // Renaming the object type field + sh:datatype xsd:string.] +sdo:Book triply:graphqlName "PieceOfArt". // Renaming the object type +``` +Then the corresponding object type would be: +```graphql +type PieceOfArt { + id:ID! + name:[XsdString]! +} +``` +### Queries +The user can query for objects using their unique ID. Also, they can query for objects of a specific type along with fields, and get nested information. Last, the user can get information by filtering results. Let's see some important concepts. + + +#### Global Object identification +For reasons such as caching, the user should be able to query an object by their unique ID. This is possible using global object identification, using the `node(id:ID)` query. +An example: + +```graphql +{ + node(id: "https://example.org/book/Odyssey") { + id + } +} +``` + +For more information on global object identification, see [graphql specification](https://graphql.org/learn/global-object-identification/). + +#### Pagination +A simple query would be: + ```graphql +{ + BookConnection { + edges { + node { + id + title + } + } + } +} + ``` +The results would include the IRIs of books together with their titles and would be paginated. + +In order to paginate through a large number of results, our GraphQL implementation supports **cursor-based pagination using connections**. For more information, please visit the Relay project's [cursor-based connection pagination specification](https://relay.dev/graphql/connections.htm). + +#### Filtering +When you query for objects, you might want to get back objects based on specific values in certain fields. You can do this by filtering. +#### Simple cases +For example, you can query for people with a specific id: +```graphql +{ + PersonConnection(filter: {id: "https://example.org/person/Homer"}) { + edges { + node { + id + name + } + } + } +} +``` +Another query would be to search for a person with a specific name: +```graphql +{ + PersonConnection(filter: {name: {eq: "Homer"}}) { + edges { + node { + id + name + } + } + } +} +``` + +Notice that in the second example, there is a new field for filtering called `eq`. When we want to filter on a field with returns a scalar, meaning that its value is represented by a literal in linked data, we have to use comparison operators: `eq`,`in` for equality, and `notEq` and `notIn` for inequality. The operators `in` and`notIn` are refering to lists. + +On the other hand, when we are filtering based on IDs - or in linked data terms, based on the IRI - , as in the first example, we don't use comparison operators. + + +The only idiomatic case is the literal with a language tag and `rdf:langString` as a datatype. This literal is represented as ` { value: "example-string", language: "en" }` and the corresponding scalar is `RdfsLangString` . This means that in order to filter using a value of this scalar type, you have to execute the query below: + +```graphql +{ + PersonConnection(filter: {name: {eq: {value: "Odysseus", language: "en"}}}) { + edges { + node { + id + name + } + } + } +} +``` +##### Language filtering +Additionally, there is support for filtering results based on the language tag. +An example is: +- Linked data: +```turtle +person:Odysseus a sdo:Person; + sdo:name "Odysseus"@en; + sdo:name "Οδυσσεύς"@gr. + + +shp:Person a sh:NodeShape; + sh:targetClass sdo:Person; + sh:property [ + sh:path sdo:name; + sh:datatype rdf:langString.]. +``` +- GraphQL query: +```graphql +{ + PersonConnection { + edges { + node { + id + name(language:"gr") + } + } + } +} +``` +- Results: +```graphql +{ + "data": { + "PersonConnection": { + "edges": [ + { + "node": { + "id": "https://example.org/person/Odysseus", + "name": [ + { + "value": "Οδυσσεύς", + "language": "gr" + } + ] + } + } + ] + } + } +} +``` +Our implementation supports using the HTTP Accept-Language syntax, for filtering based on a language-tag. +For example, +- GraphQL query: +```graphql +{ + PersonConnection { + edges { + node { + id + name(language:"gr, en;q=.5") + } + } + } +} +``` +- Results: +```graphql +{ + "data": { + "PersonConnection": { + "edges": [ + { + "node": { + "id": "https://example.org/person/Odysseus", + "name": [ + { + "value": "Οδυσσεύς", + "language": "gr" + }, + { + "value": "Odysseus", + "language": "en" + }, + ] + } + } + ] + } + } +} +``` + +If the writer of the shapes includes the `sh:uniqueLang` constraint, then the result returned will be a single value, instead of an array. +Thus, the example becomes: +- Linked data: +```turtle +person:Odysseus a sdo:Person; + sdo:name "Odysseus"@en; + sdo:name "Οδυσσεύς"@gr. + + +shp:Person a sh:NodeShape; + sh:targetClass sdo:Person; + sh:property [ + sh:path sdo:name; + sh:uniqueLang true; + sh:datatype rdf:langString.]. +``` +- GraphQL query: +```graphql +{ + PersonConnection { + edges { + node { + id + name(language:"gr, en;q=.5") + } + } + } +} +``` +- Results: +```graphql +{ + "data": { + "PersonConnection": { + "edges": [ + { + "node": { + "id": "https://example.org/person/Odysseus", + "name": { + "value": "Οδυσσεύς", + "language": "gr" + } + } + } + ] + } + } +} +``` +#### Advanced filtering + +Furthermore, there is possibility for nested filtering: + +```graphql +{ + BookConnection( + filter: {author: {name: {eq: "Homer"}}} + ) { + edges { + node { + id + } + } + } +} +``` +and for combination of filters: +```graphql +{ + BookConnection( + filter: {author: {name: {eq: "Homer"}}, name: {eq: "Odyssey"}} + ) { + edges { + node { + id + } + } + } +} +``` +Note: The combination of filters is executed in an **'and'** logic. \ No newline at end of file diff --git a/docs/triply-api/index.md b/docs/triply-api/index.md index 844735a7..186c3aa4 100644 --- a/docs/triply-api/index.md +++ b/docs/triply-api/index.md @@ -826,7 +826,7 @@ Result: ## GraphQL -This endpoint can be used for GraphQL queries. It uses information from user-provided SHACL shapes for the schema creation. +This endpoint can be used for GraphQL queries. It uses information from user-provided SHACL shapes for the schema creation. See more information about this subject [here](../generics/graphql). ### URI path @@ -862,411 +862,7 @@ This request is issued in the following way with the cURL command-line tool: -H 'Content-Type: application/json' ``` - ## Elasticsearch The text search API returns a list of linked data entities based on a supplied text string. The text string is matched against the text in literals and IRIs that appear in the linked data description of the returned entities. From f337bb1e8037cac0ce3284ff3e15ffb06b4afd94 Mon Sep 17 00:00:00 2001 From: Dionysia Nakou Date: Mon, 2 Sep 2024 11:57:11 +0200 Subject: [PATCH 3/9] wip --- docs/generics/Graphql.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/generics/Graphql.md b/docs/generics/Graphql.md index 83dd545c..b54ae855 100644 --- a/docs/generics/Graphql.md +++ b/docs/generics/Graphql.md @@ -172,7 +172,8 @@ For more information on global object identification, see [graphql specification #### Pagination A simple query would be: - ```graphql + +```graphql { BookConnection { edges { @@ -184,6 +185,7 @@ A simple query would be: } } ``` + The results would include the IRIs of books together with their titles and would be paginated. In order to paginate through a large number of results, our GraphQL implementation supports **cursor-based pagination using connections**. For more information, please visit the Relay project's [cursor-based connection pagination specification](https://relay.dev/graphql/connections.htm). From edf820f6795219a0851d262142c628e986ee5b25 Mon Sep 17 00:00:00 2001 From: Dionysia Nakou Date: Mon, 2 Sep 2024 12:16:53 +0200 Subject: [PATCH 4/9] fix object confusion --- docs/generics/Graphql.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/generics/Graphql.md b/docs/generics/Graphql.md index b54ae855..d7ca87b0 100644 --- a/docs/generics/Graphql.md +++ b/docs/generics/Graphql.md @@ -10,9 +10,11 @@ TriplyDB exposes a GraphQL endpoint. This endpoint uses information from user-pr The goal of this documentation is to inform users about Triply's implementation of the GraphQL endpoint. For more generic information about GraphQL, you can visit [graphql.org](https://graphql.org/) or other resources. In order to understand this documentation, you have to be familiar with the SHACL language. + +Note: in order to avoid confusion we will use the word `object` as a synonym for `resource` and `triple object` for the third element of a triple. ### Schema #### Object types -A basic element of the schema is object types, which represents the type of the objects that you can query. +A basic element of the schema is object types, which represents the type of the resources that you can query. ```graphql type Book { @@ -109,7 +111,7 @@ type Person { } ``` #### IDs -The id field is of type ID, which represents the IRI of each object. This ID is unique. +The id field is of type ID, which represents the IRI of each resource. This ID is unique. For example: ```turtle book:Odyssey a sdo:Book; @@ -133,7 +135,7 @@ Notice that if the selected name is illegal or causes a name collision, we'll re - for object types, the class IRI - for fields, the IRI of the property shape -as a subject, the above-mentioned predicate and a string literal with the custom name as object. +as a subject, the above-mentioned predicate and a string literal with the custom name as triple object. If we wanted to rename using the first example of the section, we would do: ```turtle @@ -185,13 +187,13 @@ A simple query would be: } } ``` - + The results would include the IRIs of books together with their titles and would be paginated. In order to paginate through a large number of results, our GraphQL implementation supports **cursor-based pagination using connections**. For more information, please visit the Relay project's [cursor-based connection pagination specification](https://relay.dev/graphql/connections.htm). #### Filtering -When you query for objects, you might want to get back objects based on specific values in certain fields. You can do this by filtering. +When you query for objects, you might want to get back resources based on specific values in certain fields. You can do this by filtering. #### Simple cases For example, you can query for people with a specific id: ```graphql From f13347acad53540edce658100d7f388dda0bdbe9 Mon Sep 17 00:00:00 2001 From: Dionysia Nakou Date: Mon, 2 Sep 2024 12:17:40 +0200 Subject: [PATCH 5/9] wip --- docs/triply-api/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/triply-api/index.md b/docs/triply-api/index.md index 186c3aa4..e665a431 100644 --- a/docs/triply-api/index.md +++ b/docs/triply-api/index.md @@ -826,7 +826,7 @@ Result: ## GraphQL -This endpoint can be used for GraphQL queries. It uses information from user-provided SHACL shapes for the schema creation. See more information about this subject [here](../generics/graphql). +This endpoint can be used for GraphQL queries. It uses information from user-provided SHACL shapes for the schema creation. See more information about this subject [here](../generics/Graphql.md). ### URI path From 79edc63e0888b486e23dba9ba7bc97495a92d65c Mon Sep 17 00:00:00 2001 From: Dionysia Nakou Date: Mon, 2 Sep 2024 12:20:42 +0200 Subject: [PATCH 6/9] bla --- docs/generics/Graphql.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/generics/Graphql.md b/docs/generics/Graphql.md index d7ca87b0..5ca4e877 100644 --- a/docs/generics/Graphql.md +++ b/docs/generics/Graphql.md @@ -11,7 +11,7 @@ TriplyDB exposes a GraphQL endpoint. This endpoint uses information from user-pr The goal of this documentation is to inform users about Triply's implementation of the GraphQL endpoint. For more generic information about GraphQL, you can visit [graphql.org](https://graphql.org/) or other resources. In order to understand this documentation, you have to be familiar with the SHACL language. -Note: in order to avoid confusion we will use the word `object` as a synonym for `resource` and `triple object` for the third element of a triple. +Note: in order to avoid confusion we will use the word `object` as a synonym for `resource` and `triple object` when referring to the third element of a triple. ### Schema #### Object types A basic element of the schema is object types, which represents the type of the resources that you can query. From dee7c97430c5678ea13eb92f4799c9d90ed720db Mon Sep 17 00:00:00 2001 From: Dionysia Nakou Date: Mon, 2 Sep 2024 12:22:52 +0200 Subject: [PATCH 7/9] wip --- docs/generics/Graphql.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/generics/Graphql.md b/docs/generics/Graphql.md index 5ca4e877..4d2b1f00 100644 --- a/docs/generics/Graphql.md +++ b/docs/generics/Graphql.md @@ -1,11 +1,11 @@ --- -title: "GraphQL endpoint" +title: "GraphQL implementation information" path: "/docs/graphql" --- [TOC] -# Graphql endpoint +# Graphql implementation TriplyDB exposes a GraphQL endpoint. This endpoint uses information from user-provided SHACL shapes for the schema creation. The goal of this documentation is to inform users about Triply's implementation of the GraphQL endpoint. For more generic information about GraphQL, you can visit [graphql.org](https://graphql.org/) or other resources. In order to understand this documentation, you have to be familiar with the SHACL language. From bf91eba42b6d0e9f2e3a052e64f702f52f4be9e7 Mon Sep 17 00:00:00 2001 From: Dionysia Nakou Date: Mon, 2 Sep 2024 13:16:35 +0200 Subject: [PATCH 8/9] wip --- docs/triply-api/index.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/triply-api/index.md b/docs/triply-api/index.md index e665a431..bc0a9de7 100644 --- a/docs/triply-api/index.md +++ b/docs/triply-api/index.md @@ -849,7 +849,7 @@ Perform a search using the custom query: ```json { "query": { - "{ PersonConnection { edges { node { id name } } } }" + "{ CapitalConnection { edges { node { label } } } }" } } ``` @@ -857,9 +857,9 @@ Perform a search using the custom query: This request is issued in the following way with the cURL command-line tool: ```sh - curl -X POST http://api./datasets///graphql - -d '{"query":"{ PersonConnection { edges { node { id name } } } }"}' - -H 'Content-Type: application/json' + curl -X POST https://api.triplydb.com/datasets/iish/cshapes/graphql \ + -d '{ "query":"{ CapitalConnection { edges { node { label } } } }"}' \ + -H "Content-Type: application/json" ``` From 63067125c37507449be83581ce8a1ef40b715ad8 Mon Sep 17 00:00:00 2001 From: Dionysia Nakou Date: Mon, 2 Sep 2024 14:07:02 +0200 Subject: [PATCH 9/9] add in getting started --- docs/triply-db-getting-started/index.md | 2 +- docs/triply-db-getting-started/viewing-data/index.md | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/triply-db-getting-started/index.md b/docs/triply-db-getting-started/index.md index a059e5fb..353a4d6d 100644 --- a/docs/triply-db-getting-started/index.md +++ b/docs/triply-db-getting-started/index.md @@ -2,7 +2,7 @@ # TriplyDB Overview -TriplyDB allows you to store, publish, and use linked data knowledge graphs. TriplyDB makes it easy to upload linked data and expose it through various APIs, including SPARQL, Elasticsearch, Linked Data Fragments, and REST. +TriplyDB allows you to store, publish, and use linked data knowledge graphs. TriplyDB makes it easy to upload linked data and expose it through various APIs, including SPARQL, GraphQL, Elasticsearch, Linked Data Fragments, and REST. Learn more about the following features: diff --git a/docs/triply-db-getting-started/viewing-data/index.md b/docs/triply-db-getting-started/viewing-data/index.md index 5946b58d..f30b53e7 100644 --- a/docs/triply-db-getting-started/viewing-data/index.md +++ b/docs/triply-db-getting-started/viewing-data/index.md @@ -178,7 +178,9 @@ After setting the destination, you will be redirected to the SPARQL query new pa When a dataset has a running Elasticsearch service, textual searches can be performed over the entire dataset. Text search with Elasticsearch works like a search engine and returns any node that contains your search term, or contains the search term in any of its properties. It is also possible to write a custom query using the Elasticsearch [Query DSL (Domain Specific Language)](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html). +## GraphQL +When a dataset includes shapes, there is also a functional GraphQL endpoint. Queries can be performed using [GraphQL language](https://graphql.org/). For more information on the schema and possible queries, also read [this document](../../generics/Graphql.md). ## Insights