Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure querying and mutating data with appropriate contexts works correctly #51

Closed
sklarman opened this issue Feb 18, 2020 · 0 comments
Closed
Assignees

Comments

@sklarman
Copy link
Collaborator

sklarman commented Feb 18, 2020

Problem:
Currently the mutation (at least the one pushing the data to the in-memory store) uses an incorrect context, which seems to be working fine on the surface, but generally is wrong and can lead to incorrect behavior in some (edge) cases. However, when we use the correct context instead some queries break.

We need to ensure the correct context is used inside the API and it gives the expected results on the query-level.

Details
Let's use the ontology from our documentation.

Whenever we convert our JSONs to RDF inside Staple API, e.g.,

  1. when pushing inputs to the in-memory back-end
  2. when reading objects from MongoDB and putting and converting them to RDF in cache

we should be always using this context:

context 1:

{
  "_id": "@id",
  "_type": "@type",
  "Agent": "http://example.com/Agent",
  "Organization": "http://example.com/Organization",
  "Person": "http://example.com/Person",
  "name": "http://example.com/name",
  "age": "http://example.com/age",
  "revenue": "http://example.com/revenue",
  "isMarried": "http://example.com/isMarried",
  "employee": {
      "@id": "http://example.com/employee",
      "@type": "@id"
  },
  "customerOf": {
      "@id": "http://example.com/customerOf",
      "@type": "@id"
  }
}

instead of this one:

context 2:

{
  "_id": "@id",
  "_type": "@type",
  "Agent": "http://example.com/Agent",
  "Organization": "http://example.com/Organization",
  "Person": "http://example.com/Person",
  "name": "http://example.com/name",
  "age": "http://example.com/age",
  "revenue": "http://example.com/revenue",
  "isMarried": "http://example.com/isMarried",
  "employee": "http://example.com/employee",
  "customerOf": "http://example.com/customerOf"
}

Basically it's about distinguishing between object properties and datatype properties. The current schema-generating script already creates context 1 additionally to context 2 and puts it into the schemaMapping object as schemaMapping["@context2"]. We need to use both contexts in different cases because context 2 is suitable only for the user for converting GraphQL responses (so it should be still exposed via _CONTEXT query), as they are of slightly different shape than JSONs that we use in the inputs and in MongoDB.

You can see the different behavior when converting data to RDF:

{
"@context": context 1,
"_id": "http://test1",
"employee": [ "http://test2" ]
}

This gives:

<http://test1> <http://example.com/employee> <http://test2> .

Instead:

{
"@context": context 2,
"_id": "http://test1",
"employee": [ "http://test2" ]
}

This gives:

<http://test1> <http://example.com/employee> "http://test2" .

The object in the triple in the first case is interpreted as a node, which is correct, and in the other case as a string, which is wrong.

Now, when we tried to replace the contexts in the pushObjectToBackend on the in-memory adapter the data in the database was created correctly, but then the querying broke. So this has to be fixed thoroughly across the entire API.

Tests:
Here are two tests that should verify the correct implementation:

test 1:
Load the following data into the Staple API using the pushObjectToBackend method:

[
    {
        "_id": "http://example.com/bank",
        "_type": [
            "Organization"
        ],
        "name": "National Bank",
        "revenue": 12.5,
        "employee": [
            {
                "_id": "http://example.com/john"
            }
        ]
    },
    {
        "_id": "http://example.com/mobile",
        "_type": [
            "Organization"
        ],
        "name": "Mobile Network Provider",
        "revenue": 10,
        "employee": [
            {
                "_id": "http://example.com/mark"
            }
        ]
    },
    {
        "_id": "http://example.com/john",
        "_type": [
            "Person"
        ],
        "name": "John Smith",
        "age": 35,
        "isMarried": true,
        "customerOf": [
            {
                "_id": "http://example.com/bank"
            },
            {
                "_id": "http://example.com/mobile"
            }
        ]
    },
    {
        "_id": "http://example.com/mark",
        "_type": [
            "Person"
        ],
        "name": "Mark Brown",
        "age": 40,
        "isMarried": false,
        "customerOf": [
            {
                "_id": "http://example.com/bank"
            }
        ]
    }
]

Verify that the database contains this RDF data:

<http://example.com/bank> <http://example.com/employee> <http://example.com/john> .
<http://example.com/bank> <http://example.com/name> "National Bank" .
<http://example.com/bank> <http://example.com/revenue> "1.25E1"^^<http://www.w3.org/2001/XMLSchema#double> .
<http://example.com/john> <http://example.com/age> "35"^^<http://www.w3.org/2001/XMLSchema#integer> .
<http://example.com/john> <http://example.com/customerOf> <http://example.com/bank> .
<http://example.com/john> <http://example.com/customerOf> <http://example.com/mobile> .
<http://example.com/john> <http://example.com/isMarried> "true"^^<http://www.w3.org/2001/XMLSchema#boolean> .
<http://example.com/john> <http://example.com/name> "John Smith" .
<http://example.com/mark> <http://example.com/age> "40"^^<http://www.w3.org/2001/XMLSchema#integer> .
<http://example.com/mark> <http://example.com/customerOf> <http://example.com/bank> .
<http://example.com/mark> <http://example.com/isMarried> "false"^^<http://www.w3.org/2001/XMLSchema#boolean> .
<http://example.com/mark> <http://example.com/name> "Mark Brown" .
<http://example.com/mobile> <http://example.com/employee> <http://example.com/mark> .
<http://example.com/mobile> <http://example.com/name> "Mobile Network Provider" .
<http://example.com/mobile> <http://example.com/revenue> "10"^^<http://www.w3.org/2001/XMLSchema#integer> .

Now query for:

{
  Organization {
    _id
    _type
    name
    employee {
      _id
      _type
      name
      customerOf {
        _id
      }
    }
  }
}

You should get the full answer with employee and customerOf fields populated as expected.

Test 2:
Insert the same but with mutations:

mutation {
  Person(input: {
    _id: "http://example.com/john"
    name: "John Smith"
    customerOf: [
      "http://example.com/bank"
      "http://example.com/mobile"
    ]
  })
}
mutation {
  Person(input: {
    _id: "http://example.com/mark"
    name: "Mark Brown"
    customerOf: [
      "http://example.com/bank"
    ]
  })
}
mutation {
  Organization(input: {
    _id: "http://example.com/bank"
    name: "National Bank"
    employee: [
      "http://example.com/john" 
    ]
  })
}
mutation {
  Organization(input: {
    _id: "http://example.com/mobile"
    name: "Mobile Network Provider"
    employee: [
      "http://example.com/mark" 
    ]
  })
}

Follow the same steps as before.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants