[PP-1] Consider not storing the ComponentTreeStructure data type as a JSON blob

Created on 15 August 2024, 3 months ago
Updated 6 September 2024, 2 months ago

Overview

After šŸ“Œ `ComponentTreeStructure` date type: simplify the stored structure Active lands, there's another thing that @longwave pointed out (that I happened to have thought overnight too šŸ˜‡): why use a JSON blob at all for the tree prop aka the ComponentTreeStructure data type?

Or, does this really need to be JSON at all? Can we just have a flat table?

parent,slot,delta,uuid,component
ROOT_UUID,root,0,uuid-root-1,provider:two-col
ROOT_UUID,root,1,uuid-root-2,provider:marquee
ROOT_UUID,root,2,uuid-root-3,provider:marquee
uuid-root-1,firstColumn,0,uuid4-author1,provider:person-card
uuid-root-1,firstColumn,1,uuid2-submitted,provider:elegant-date
uuid-root-1,secondColumn,0,uuid5-author2,provider:person-card
uuid-root-2,content,0,uuid-author3,provider:person-card

ā€” https://git.drupalcode.org/project/experience_builder/-/merge_requests/1...

Proposed resolution

Discuss.

User interface changes

None.

šŸ“Œ Task
Status

Active

Component

Data model

Created by

šŸ‡§šŸ‡ŖBelgium wim leers Ghent šŸ‡§šŸ‡ŖšŸ‡ŖšŸ‡ŗ

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @wim leers
  • šŸ‡«šŸ‡®Finland lauriii Finland

    Would it be possible to document what are the benefits and downsides of using a flat table over a JSON blob? Based on the issue summary, it isn't clear to me what are the trade-offs involved in this decision.

  • Assigned to effulgentsia
  • Status changed to Active 3 months ago
  • šŸ‡¬šŸ‡§United Kingdom longwave UK
  • šŸ‡§šŸ‡ŖBelgium wim leers Ghent šŸ‡§šŸ‡ŖšŸ‡ŖšŸ‡ŗ

    Thoughts:

    • I agree a JSON blob is overkill and a table is in principle sufficient.
    • ā€¦ but Drupal's Entity Field system assumes every field prop corresponds to a data type (true here too), and that data type must be a single column in the database (not true here), and is always a primitive (the data type class must implement \Drupal\Core\TypedData\PrimitiveInterface if that data type is used for a field property ā€” AFAICT)
    • So then IMHO the question becomes: how do we store such a table in a single DB column?

    The only exception I can think of (right now, in the little time I have this morning while writing this up to ensure we follow through!): the PathItem field type, which essentially is a computed field type that stores its data in another database table and does the necessary additional DB queries.

    Maybe that can work? That maybe actually gets closer to @effulgentsia's original proposal at āœØ JSON-based data storage proposal for component-based page building Active , where he proposed to do some deduplication stuff that most of us wanted to defer to later?

    We could then literally have a single DB table for all XB uses, by expanding the columns from

    parent,slot,delta,uuid,component
    

    (@longwave's comment)
    to:

    entity_type_id,entity_id,field_name,parent,slot,delta,uuid,component
    

    ā€¦ which would not violate the 3.2.4 Facilitating `component props` changes section in docs/data-model.md.

  • šŸ‡¬šŸ‡§United Kingdom longwave UK

    One benefit is this becomes trivial:

    An upgrade path for a `component` would require logic somewhat like this:

    1. SQL query to search the _tree_ JSON blob for uses of this `component`, capture the UUIDs.

    SELECT uuid FROM table WHERE component = "provider:person-card"
    

    @Wim Leers additional note: we also have to consider langcode for asymmetric translations

  • šŸ‡¬šŸ‡§United Kingdom catch

    @lauriii One of the advantages here is it would (at least partially) solve the same problem of non-portable JSON queries (which are already in the XB code base) that šŸ“Œ Calculate field and component dependencies on save and store them in an easy to retrieve format Active is also trying to remove - same general problem as #5.

  • šŸ‡¬šŸ‡§United Kingdom catch

    ā€¦ but Drupal's Entity Field system assumes every field prop corresponds to a data type (true here too), and that data type must be a single column in the database (not true here), and is always a primitive (the data type class must implement \Drupal\Core\TypedData\PrimitiveInterface if that data type is used for a field property ā€” AFAICT)

    I'm not sure exactly which data isn't fitting in a single column, but could just that column be JSON (storing a flat array of whatever doesn't fit) without undermining the goal of the issue?

  • šŸ‡§šŸ‡ŖBelgium wim leers Ghent šŸ‡§šŸ‡ŖšŸ‡ŖšŸ‡ŗ

    #5++

    #6++

    #7: an XB field must store a tree of components + sources for their props values. This issue proposes to store that tree as a list, so not as a single column in a single row, but as multiple columns in multiple rows. That's what I was trying to convey in #4, and is also why I pointed to @effulgentsia's "deduplication" proposal (we could implement this by storing a single value for each XB field revision's tree, with that value pointing to a foreign key in another table, where @longwave's proposed columns could then be used).

  • Issue was unassigned.
  • šŸ‡ŗšŸ‡øUnited States effulgentsia

    I think this proposal makes sense. My initial thinking behind JSON for this was thinking we wanted to store it as a tree. But since we've already changed that to a flat JSON representation, I don't think JSON for this part has any special value.

    Drupal's Entity Field system assumes every field prop corresponds to a data type and that data type must be a single column in the database

    I think what we could do is store this as a multi-valued field. If we want to keep tree and values as a single field, we could do that by each item containing the following columns: component_instance_id, component, parent, slot, delta_in_slot, props, where that last one is the JSON props source/expression/values for that component instance.

    However, at some point, I think it will make sense for us to model this as two fields: in other words, pull the props column out of the above suggestion and make it its own separate field from the field representing the tree. Not sure if we want to jump to the two field implementation as part of this issue or continue to keep it as one field until we separately discuss the pros and cons of two fields vs one.

  • šŸ‡øšŸ‡ŖSweden johnwebdev

    #4

    We could then literally have a single DB table for all XB uses, by expanding the columns from

    entity_type_id,entity_id,field_name,parent,slot,delta,uuid,component

    I'm not sure that would with revisions and sync/async translations?

  • šŸ‡³šŸ‡æNew Zealand quietone

    Removed duplicate related item.

Production build 0.71.5 2024