BlueBrain / nexus-forge

Building and Using Knowledge Graphs made easy
https://nexus-forge.readthedocs.io
GNU Lesser General Public License v3.0
38 stars 19 forks source link

How does Nexus Forge handle linked resources on creation/update? #197

Closed tobiasschweizer closed 2 years ago

tobiasschweizer commented 2 years ago

Hi

I have a question regarding the representation of linked resources in JSON-LD on creation/update.

Example:

The type Person can link to an Organization via the affiliation property.

org_mapping = DictionaryMapping("""
    type: Organization
    name: x['name']
    email: x['email']
""")

test_org = { 'name': 'my firm', 'email': 'info@myfirm.com'}

org_mapped = forge.map(test_org, org_mapping)
forge.register(org_mapped)
_register_one True
person_mapping = DictionaryMapping("""
    type: Person
    familyName: x['fname']
    givenName: x['gname']
    identifier: x['orcid']
    name: x['fname']
""")

test_person = { 'fname': 'Duck', 'gname': 'Donald', 'orcid': 'https://orcid.org/0000-0001-2345-6789'}

person_mapped = forge.map(test_person, person_mapping, na='nan')
person_mapped.affiliation = org_mapped

forge.register(person_mapped)
_register_one True

And then in Nexus I see the following data:

{
  {
    "@context": {...}
   },
  "@type": "Person",
  "affiliation": {
    "@id": "https://myserver/v1/resources/org/proj/_/c6e07950-1cbc-4022-bd40-d2d1771e0e0b",
    "@type": "Organization",
    "email": "info@myfirm.com",
    "name": "my firm"
  },
  "familyName": "Duck",
  "givenName": "Donald",
  "identifier": "https://orcid.org/0000-0001-2345-6789",
  "name": "Duck"
}

and

{
  {
    "@context": {...}
   },
  "@type": "Organization",
  "email": "info@myfirm.com",
  "name": "my firm"

In Nexus, there are now two instances: a Person linking to an Organization. But the Organization is also embedded inside the JSON-LD representing the Person.

Is Organization stored redundantly in Nexus? What happens if the Organization resource is mutated (consistency of the data embedded in Person)?

Does the compacted JSON-LD correspond to the original payload sent to the Nexus Delta API (I noted that the @id is missing: I assume this is because the @id was created by the system and is thus not part of the payload)?

MFSY commented 2 years ago

Hi @tobiasschweizer ,

The following call:

person_mapped.affiliation = org_mapped

will copy as value of person_mapped.affiliation the dict in org_mapped.

If you only want to refer to org_mapped, I recommend to do:

person_mapped.affiliation = Resource.from_json({"@id": org_mapped.id, "@type":"Organization"}) This way you don't duplicate the organisation payload and do not have to handle consistency.

With BlueBrainNexus store, a call to :

forge.register(org_mapped) should add an 'id' attribute to the payload.