archesproject / arches

Arches is a web platform for creating, managing, & visualizing geospatial data. Arches was inspired by the needs of the Cultural Heritage community, particularly the widespread need of organizations to build & manage cultural heritage inventories
GNU Affero General Public License v3.0
219 stars 144 forks source link

Rearchitect the LabelBasedGraph / Disambiguated Graph #8032

Open chrabyrd opened 2 years ago

chrabyrd commented 2 years ago

The LabelBasedGraph is becoming further integrated into arches-core and various arches projects; this increased use has resulted in a direct need for a more descriptive data structure, additional data returned, and reduced database queries. ( Also, we should consolidate around a name )

Specifically, the proposed changes are:

Consider a simplified Person resource:

    {
        "@displaydescription": 'DISPLAY DESCRIPTION', 
        "@displayname": 'DISPLAY NAME', 
        "@graph_id": '1111111-11111-1111111', 
        "@legacyid": null, 
        "@map_popup": null,
        "@resourceinstanceid": '2222222-22222-222222222',
        "@type": "resource_instance",
        "Name": {
            "@type": "node",
            "@node_id": "333333-3333-333333333",
            "@tile_id": "444444-4444-444444444",
            "First Name": {
                "@type": "node",
                "@node_id": "55555-55555-5555555",
                "@tile_id": "66666-66666-6666666",
                "@value": "Bob",
            },
            "Last Name": null,
        },
        "Nicknames": {
            "@type": "nodeset",
            "@node_id": "77777-7777-7777777",
            "@value": [
                {
                    "@type": "node",
                    "@node_id": "77777-7777-7777777",
                    "@tile_id": "99999-99999-999999",
                    "@value": "Bobert"
                }
            ],
        },
        "Knacknames": [],
        "Eye Color": null,
        "Pets": {
            "@type": "nodeset",
            "@node_id": "AAAAA-AAAA-AAAAAAA",
            "@value": [
                {
                    "@type": "node",
                    "@node_id": "AAAAA-AAAA-AAAAAAA",
                    "@tile_id": "CCCCC-CCCCC-CCCCCC",
                    "@value": "Bark Ruffalo"
                },
                {
                    "@type": "node",
                    "@node_id": "AAAAA-AAAA-AAAAAAA",
                    "@tile_id": "DDDDD-DDDDD-DDDDDD",
                    "@value": "Meowry Pawvitch"
                }
            ],
        }
    }

Without having seen the Person graph, we can infer a good deal from this:

However, some questions remain:

chrabyrd commented 2 years ago

Personally, I feel if we tweak the proposed pattern a little that some questions will answer themselves. The above Person LabelBasedGraph is roughly what fell out of committee; below is my personal spin on the proposed pattern:

    {
        "@display_description": 'DISPLAY DESCRIPTION', 
        "@display_name": 'DISPLAY NAME', 
        "@graph_id": '1111111-11111-1111111', 
        "@legacy_id": undefined, 
        "@map_popup": null,
        "@resource_instance_id": '2222222-22222-222222222',
        "@datatype": "resource_instance",
        "@nodes": [
            {
                "@display_name": "Name",
                "@datatype": "semantic",
                "@cardinality": "n",
                "@node_id": "333333-3333-333333333",
                "@tile_id": "444444-4444-444444444",
                "@direct_children": [
                    {
                        "@display_name": "First Name",
                        "@datatype": "string",
                        "@node_id": "55555-55555-5555555",
                        "@tile_id": "66666-66666-6666666",
                        "@value": "Bob",
                    },
                    {
                        "@display_name": "Last Name",
                        "@datatype": "string",
                        "@node_id": "55555-55555-5555555",
                        "@value": undefined,
                    }
                ]
            },
            {
                "@display_name": "Nicknames",
                "@datatype": "string",
                "@cardinality": "n",
                "@node_id": "77777-7777-7777777",
                "@value": [
                    {
                        "@tile_id": "99999-99999-999999",
                        "@value": "Bobert"
                    }
                ],
            },
            {
                "@display_name": "Knacknames",
                "@datatype": "string",
                "@cardinality": "n",
                "@node_id": "88888-88888-88888888",
                "@value": undefined
            },
            {
                "@display_name": "Eye Color",
                "@datatype": "string",
                "@cardinality": 1,
                "@node_id": "95499-94599-99945999",
                "@value": undefined
            },
            {
                "@display_name": "Pets",
                "@datatype": "resource_instance_list",
                "@cardinality": "n",
                "@node_id": "AAAAA-AAAA-AAAAAAA",
                "@value": [
                    {
                        "@datatype": "resource_instance",
                        "@cardinality": 1,
                        "@tile_id": "CCCCC-CCCCC-CCCCCC",
                        "@value": "Bark Ruffalo"
                    },
                    {
                        "@datatype": "resource_instance",
                        "@cardinality": 1,
                        "@tile_id": "DDDDD-DDDDD-DDDDDD",
                        "@value": "Meowry Pawvitch"
                    }
                ],
            },
        ]
    }

With the above pattern, we get the following wins:

However, some issues still remain:

aj-he commented 2 years ago

@chrabyrd it feels this is a significant change to the structure. The great thing about the original one was you could following the structure using the node names as keys, making it much quicker to use it in the UI.

The HTML export templates are built around this principal. You could chain through the node names and then retrieve the @display_value...

{{ resource_data|val_from_key:"System Reference Numbers"|val_from_key:"PrimaryReferenceNumber"|val_from_key:"Primary Reference Number"|val_from_key:"@display_value" }}

The original structure provided that "human readable" structure which felt like the original purpose. v2 added some additional metadata and the more consistent @display_value, which was good but generally maintained the same overall pattern.

Adding additional @metadata attributes within the existing structure would be more preferable.

should the cardinality value be different datatypes?