# GraphQL inverse traversal

**URL:** <https://community.stardog.com/t/graphql-inverse-traversal/2324>\
**Category:** Stardog Studio\
**Created:** [March 20, 2020, 7:14pm UTC](https://community.stardog.com/t/graphql-inverse-traversal/2324 "2020-03-20T19:14:59Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![R3000](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.stardog.com/r3000/32/358_2.png) [@R3000](https://community.stardog.com/u/R3000)\
**Post date:** [March 20, 2020, 7:14pm UTC](https://community.stardog.com/t/graphql-inverse-traversal/2324/1 "2020-03-20T19:14:59Z")

</div>

So once I loaded starwars.ttl I am able to execute a query like:

```auto
{
    Human{
        name
        appearsIn{
            name
        }
    }
}

```

produces nicely:

```auto
{
  "data": [
    {
      "name": "Luke Skywalker",
      "appearsIn": [
        {
          "name": "Return of the Jedi"
        },
        {
          "name": "A New Hope"
        },
        {
          "name": "The Empire Strikes Back"
        }
      ]
    },
    {
      "name": "Han Solo",
      "appearsIn": [
        {
          "name": "A New Hope"
        },
        {
          "name": "The Empire Strikes Back"
        },
        {
          "name": "Return of the Jedi"
        }
      ]
    },
    {
      "name": "Leia Organa",
      "appearsIn": [
        {
          "name": "The Empire Strikes Back"
        },
        {
          "name": "A New Hope"
        },
        {
          "name": "Return of the Jedi"
        }
      ]
    },
    {
      "name": "Darth Vader",
      "appearsIn": [
        {
          "name": "Return of the Jedi"
        },
        {
          "name": "A New Hope"
        },
        {
          "name": "The Empire Strikes Back"
        }
      ]
    },
    {
      "name": "Wilhuff Tarkin",
      "appearsIn": {
        "name": "A New Hope"
      }
    }
  ]
}

```

- Now how can I get the inverse - show me all Humans for each episode?  
owl:inverseOf is nice but how can use it? Shall I add a few turtle statements to starwars.ttl to define the inverse relation?

Regards,  
Radu

---

<div class="post-metadata">

**Author:** ![stephen](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.stardog.com/stephen/32/27_2.png) [@stephen](https://community.stardog.com/u/stephen)\
**Post date:** [March 24, 2020, 12:30pm UTC](https://community.stardog.com/t/graphql-inverse-traversal/2324/2 "2020-03-24T12:30:30Z")

</div>

Hi Radu,

You would just need to add one triple to your dataset, in fact: `:featuresCharacter owl:inverseOf :appearsIn .`

If you add that, enable reasoning, and slightly rewrite your query, you can get what you're looking for:

 ![image](https://canada1.discourse-cdn.com/flex030/uploads/stardog/original/1X/5d1f74cf6346f8727d4d270d6aaf16f0ab4b1fc9.png)

---

<div class="post-metadata">

**Author:** ![stephen](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.stardog.com/stephen/32/27_2.png) [@stephen](https://community.stardog.com/u/stephen)\
**Post date:** [March 24, 2020, 12:34pm UTC](https://community.stardog.com/t/graphql-inverse-traversal/2324/3 "2020-03-24T12:34:23Z")

</div>

As a follow-up, if you want to limit the query to just Humans, you can do that too:

 ![image](https://canada1.discourse-cdn.com/flex030/uploads/stardog/original/1X/fa7ced284334d88754495164a26b86d4c66c1db7.png)

---

<div class="post-metadata">

**Author:** ![R3000](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.stardog.com/r3000/32/358_2.png) [@R3000](https://community.stardog.com/u/R3000)\
**Post date:** [March 24, 2020, 4:19pm UTC](https://community.stardog.com/t/graphql-inverse-traversal/2324/4 "2020-03-24T16:19:45Z")

</div>

Thank you Stephen,

Your suggestion makes total sense. I will be trying out.

To leverage the new HTTP API shall I use "sparql\_update" as documented below or do a POST host:port/db/default with what headers for ttl file?

```auto
### [SPARQL update](https://www.stardog.com/docs/#_sparql_update)

```

GET | POST /{db}/update → text/boolean

```auto

The SPARQL endpoint for updating the database with SPARQL Update. The valid Accept types are `application/sparql-update` `or application/x-www-form-urlencoded` . Response is the result of the update operation as text, eg `true` or `false` .

```

---

<div class="post-metadata">

**Author:** ![R3000](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.stardog.com/r3000/32/358_2.png) [@R3000](https://community.stardog.com/u/R3000)\
**Post date:** [March 24, 2020, 5:24pm UTC](https://community.stardog.com/t/graphql-inverse-traversal/2324/5 "2020-03-24T17:24:53Z")

</div>

So I was able to load ttl via api using:

- 'content-type': "application/x-turtle"
- and using HTTP POST host:port/Test3?default endpoint

I've appended the last triple as follows:

```auto
data = original_starwars_ttl + """
:featuresCharacter owl:inverseOf :appearsIn ."""
response = requests.request("POST", url, data = data, headers=headers, verify=False)
print(response.status_code)

```

But this graphql **in Stardog Studio** returns zero data ☹

```auto
{
    Episode{
        name
        featuresCharacter{
            name
        }
    }
}

```

A brand new database.

- What is wrong?

Thanks,  
Radu

---

<div class="post-metadata">

**Author:** ![stephen](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.stardog.com/stephen/32/27_2.png) [@stephen](https://community.stardog.com/u/stephen)\
**Post date:** [March 24, 2020, 5:47pm UTC](https://community.stardog.com/t/graphql-inverse-traversal/2324/6 "2020-03-24T17:47:18Z")

</div>

Are you enabling reasoning when running the query (the toggle to the right of the Show Plan button)?

---

<div class="post-metadata">

**Author:** ![R3000](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.stardog.com/r3000/32/358_2.png) [@R3000](https://community.stardog.com/u/R3000)\
**Post date:** [March 26, 2020, 6:21pm UTC](https://community.stardog.com/t/graphql-inverse-traversal/2324/7 "2020-03-26T18:21:55Z")

</div>

Wow! - magic - "Reasoning" On button - did the trick - thank you. Now I am getting:

```auto
{
  "data": [
    {
      "name": "A New Hope",
      "featuresCharacter": [
        {
          "name": "C-3PO"
        },
        {
          "name": "R2-D2"
        },
        {
          "name": "Leia Organa"
        },
        {
          "name": "Wilhuff Tarkin"
        },
        {
          "name": "Darth Vader"
        },
        {
          "name": "Han Solo"
        },
        {
          "name": "Luke Skywalker"
        }
      ]
    },
    {
      "name": "The Empire Strikes Back",
      "featuresCharacter": [
        {
          "name": "Darth Vader"
        },
        {
          "name": "C-3PO"
        },
        {
          "name": "R2-D2"
        },
        {
          "name": "Luke Skywalker"
        },
        {
          "name": "Leia Organa"
        },
        {
          "name": "Han Solo"
        }
      ]
    },
    {
      "name": "Return of the Jedi",
      "featuresCharacter": [
        {
          "name": "R2-D2"
        },
        {
          "name": "Darth Vader"
        },
        {
          "name": "Leia Organa"
        },
        {
          "name": "Han Solo"
        },
        {
          "name": "Luke Skywalker"
        },
        {
          "name": "C-3PO"
        }
      ]
    }
  ]
}

```

---

<div class="post-metadata">

**Author:** ![R3000](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.stardog.com/r3000/32/358_2.png) [@R3000](https://community.stardog.com/u/R3000)\
**Post date:** [March 27, 2020, 4:02pm UTC](https://community.stardog.com/t/graphql-inverse-traversal/2324/8 "2020-03-27T16:02:01Z")

</div>

Zach,

Ok trying to create the inverse relation in JSON-LD per speck at [https://w3c.github.io/json-ld-syntax/#reverse-properties](https://w3c.github.io/json-ld-syntax/#reverse-properties). Added @reverse ex:containedIn inside the context - the rest stayed the same. Once I have added the json-ld - there is no triple added - that would say ... owl:reversOf ...

- Does Stardog honor @reverse directive in JSON-LD?

```auto
{
  "@context": {
    "dc11": "http://purl.org/dc/elements/1.1/",
    "ex": "http://example.org/vocab#",
    "xsd": "http://www.w3.org/2001/XMLSchema#",
    "ex:contains": {
      "@type": "@id"
    },
    "ex:containedIn": { 
        "@reverse": "http://example.org/vocab#contains" 
    }
  }

```

---

<div class="post-metadata">

**Author:** ![R3000](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.stardog.com/r3000/32/358_2.png) [@R3000](https://community.stardog.com/u/R3000)\
**Post date:** [March 30, 2020, 1:29am UTC](https://community.stardog.com/t/graphql-inverse-traversal/2324/9 "2020-03-30T01:29:37Z")

</div>

This [example](https://www.w3.org/TR/json-ld11/#example-114-using-reverse-to-define-reverse-properties) is useful - loaded into Stardog - but still trying to figure out the graphql query returning zero rows with reasoning on:  
{  
ex\_children{  
name  
}  
}

---

<div class="post-metadata">

**Author:** ![zachary.whitley](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.stardog.com/zachary.whitley/32/94_2.png) [@zachary.whitley](https://community.stardog.com/u/zachary.whitley)\
**Post date:** [March 30, 2020, 12:23pm UTC](https://community.stardog.com/t/graphql-inverse-traversal/2324/10 "2020-03-30T12:23:01Z")

</div>

That's a good question. I guess that would require creating an owl:inverseOf. I would first check to see if that axiom is being created after importing the json-ld and then if it was make sure that it is contained in a graph, or default graph that Stardog will be using for reasoning. If it's there and in the correct graph it should work.

---

<div class="post-metadata">

**Author:** ![R3000](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.stardog.com/r3000/32/358_2.png) [@R3000](https://community.stardog.com/u/R3000)\
**Post date:** [March 30, 2020, 6:49pm UTC](https://community.stardog.com/t/graphql-inverse-traversal/2324/11 "2020-03-30T18:49:19Z")

</div>

Zach,

I don't think the the owl:inverseOf has been generated during json-ld data add - see results below. You can try it yourself, right?

 ![image](https://canada1.discourse-cdn.com/flex030/uploads/stardog/original/1X/998aad39a8f67294c9fd3af1c79aa4ae582b54dc.png)

---

<div class="post-metadata">

**Author:** ![R3000](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.stardog.com/r3000/32/358_2.png) [@R3000](https://community.stardog.com/u/R3000)\
**Post date:** [March 31, 2020, 6:07pm UTC](https://community.stardog.com/t/graphql-inverse-traversal/2324/12 "2020-03-31T18:07:57Z")

</div>

Again the above select \* results are after importing the following:

```auto
{
  "@context": { "name": "http://example.com/vocab#name",
    "children": { "@reverse": "http://example.com/vocab#parent" }
  },
  "@id": "#homer",
  "name": "Homer",
  "children": [
    {
      "@id": "#bart",
      "name": "Bart"
    }, {
      "@id": "#lisa",
      "name": "Lisa"
    }
  ]
}

```

- Any resolution yet?

---

<div class="post-metadata">

**Author:** ![stephen](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.stardog.com/stephen/32/27_2.png) [@stephen](https://community.stardog.com/u/stephen)\
**Post date:** [March 31, 2020, 7:05pm UTC](https://community.stardog.com/t/graphql-inverse-traversal/2324/13 "2020-03-31T19:05:56Z")

</div>

Hi Radu,

According to the example you pasted from [the spec](https://www.w3.org/TR/json-ld11/#example-114-using-reverse-to-define-reverse-properties), Stardog is behaving correctly. You can verify this in the example box by switching it over to Turtle or Statements.

From reading the spec itself, `@reverse` does not have to do with inferencing/reasoning at all; it is merely a way to define relationships as o -\> p -\> s instead of s -\> p -\> o.

If you want to use inferencing to see this relationship, you can define explicit `owl:inverseOf` relationships in your JSON-LD:

```auto
{
  "@context": {
    "dc11": "http://purl.org/dc/elements/1.1/",
    "ex": "http://example.org/vocab#",
    "xsd": "http://www.w3.org/2001/XMLSchema#",
    "owl": "http://www.w3.org/2002/07/owl#",
    "ex:contains": {
      "@type": "@id"
    },
    "ex:containedIn": {
        "owl:inverseOf": "http://example.org/vocab#contains"
    }
  }
}

```

---

<div class="post-metadata">

**Author:** ![R3000](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.stardog.com/r3000/32/358_2.png) [@R3000](https://community.stardog.com/u/R3000)\
**Post date:** [March 31, 2020, 9:32pm UTC](https://community.stardog.com/t/graphql-inverse-traversal/2324/14 "2020-03-31T21:32:16Z")

</div>

Stephen,

I have loaded this json-ld:

```auto
{
  "@context": {
    "dc11": "http://purl.org/dc/elements/1.1/",
    "ex": "http://example.org/vocab#",
    "xsd": "http://www.w3.org/2001/XMLSchema#",
    "owl": "http://www.w3.org/2002/07/owl#",
    "ex:contains": {
      "@type": "@id"
    },
    "ex:containedIn": {
        "owl:inverseOf": "http://example.org/vocab#contains"
    }
  },
  "@graph": [
    {
      "@id": "http://example.org/library",
      "@type": "ex:Library",
      "dc11:title": "My Library",
      "ex:contains": "http://example.org/library/the-republic"
    },
    {
      "@id": "http://example.org/library/the-republic",
      "@type": "ex:Book",
      "dc11:creator": "Plato",
      "dc11:title": "The Republic",
      "ex:contains": "http://example.org/library/the-republic#introduction"
    },
    {
      "@id": "http://example.org/library/the-republic#introduction",
      "@type": "ex:Chapter",
      "dc11:description": "An introductory chapter on The Republic.",
      "dc11:title": "The Introduction"
    }
  ]
}

```

but the graphql returns no rows:

```auto
{
    ex_Book {        
        dc11_title
        ex_contains{
            dc11_title
        }
        ex_containedIn{
            dc11_title
        }
    }
}

```

however this returns one row:

```auto
{
    ex_Book {        
        dc11_title
        ex_contains{
            dc11_title
        }
    }
}

```

---

<div class="post-metadata">

**Author:** ![stephen](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.stardog.com/stephen/32/27_2.png) [@stephen](https://community.stardog.com/u/stephen)\
**Post date:** [April 1, 2020, 1:25pm UTC](https://community.stardog.com/t/graphql-inverse-traversal/2324/15 "2020-04-01T13:25:02Z")

</div>

Hi Radu,

JSON-LD seems to be kind of finicky when it comes to specifying literals versus IRIs, and where you have to do it. I have rewritten your JSON-LD to be what you're looking for by moving the owl:inverseOf definition into the `@graph` instead of the `@context`:

```auto
{
  "@context": {
    "dc11": "http://purl.org/dc/elements/1.1/",
    "ex": "http://example.org/vocab#",
    "xsd": "http://www.w3.org/2001/XMLSchema#",
    "owl": "http://www.w3.org/2002/07/owl#",
    "ex:contains": {
      "@type": "@id"
    }
  },
  "@graph": [
    {
      "@id": "ex:containedIn",
      "owl:inverseOf": {
        "@id": "ex:contains"
      }
    },
    {
      "@id": "http://example.org/library",
      "@type": "ex:Library",
      "dc11:title": "My Library",
      "ex:contains": "http://example.org/library/the-republic"
    },
    {
      "@id": "http://example.org/library/the-republic",
      "@type": "ex:Book",
      "dc11:creator": "Plato",
      "dc11:title": "The Republic",
      "ex:contains": "http://example.org/library/the-republic#introduction"
    },
    {
      "@id": "http://example.org/library/the-republic#introduction",
      "@type": "ex:Chapter",
      "dc11:description": "An introductory chapter on The Republic.",
      "dc11:title": "The Introduction"
    }
  ]
}

```

This gives me what I think is the result you're looking for, though I need to enable reasoning to do it:

 ![image](https://canada1.discourse-cdn.com/flex030/uploads/stardog/original/1X/604553614e5c9b55955505d1437b649f953d9c8e.png)

You may want to use the CLI `stardog graphql explain` command to help you out. It will show you the SPARQL query generated by Stardog to fulfill the provided graphql query.
