Skip to content

Instantly share code, notes, and snippets.

@bearzk
Last active July 18, 2023 11:25
Show Gist options
  • Save bearzk/4603499066932a41720160345cb00507 to your computer and use it in GitHub Desktop.
Save bearzk/4603499066932a41720160345cb00507 to your computer and use it in GitHub Desktop.

Single Table Design for Dashboards

basic concept to read: https://www.dynamodbguide.com/

Also, as MongoDB is much more flexible about indices than DDB, it's less dangerous to try out STD in MongoDB.

Table Design

basic

  • collection: dashboard

  • 2 types: [dashboard, widget]

  • pk: partition key for records, how records should be grouped, allocated

  • sk: sorting key for a record inside a partition

pk+sk: primary key for pinpointing one record

type pk sk explanation
dashboard d#dashboard_id d#dashboard_id (prefixed) mongo id or any lexicographically sortable id, pk === sk
widget d#dashboard_id w#widget_id pk contains the dashboard's mongo id, sk contains the widget's own mongo id
access pattern query pagination explanation
get me a dashboard {pk: d#dashboard_id, sk: d#dashboard_id} or {sk: d#dashboard_id} NA
get me a dashboard and its widgets {pk: d#dashboard_id}, {limit, sortBy: sk ascending} {pk: d#dashboard_id, sk: {$gt: last w#widget_id}}
give me all dashboards I can see {pk: /^d#/, sk: /^d#/, acl filters}, { limit } {pk: /^d#/, acl filters, $and: [{sk: /^d#/}, {sk: {$gt: last d#dashboard_id}}]}
give me all widgets I can see {pk: /^d#/}, sk: /^w#/, acl filters}, { limit } {pk: /^d#/, acl filters, $and: [{sk: /^w#/}, {sk: {$gt: last w#widget_id}}]} all widgets belong to at least one dashboard or they don't exist
give me all widgets I can see {sk: /^w#/, acl filters} {$and: [{sk: /^w#/}, {sk: {$gt: last w#widget_id, acl filters}}]} if a widget is not necessarily bound to any dashboard, flexibility of MongoDB allows us to use sk directly, not necessarily always use pk+sk pattern, might even be the preferred way after all
update or delete one dashboard {pk: d#dashboard_id, sk: d#dashboard_id} or {sk: d#dashboard_id}
update or delete one widget {pk: d#dashboard_id, sk: w#dashboard_id} or {sk: w#dashboard_id}

One Widget belongs to many Dashboards?

type pk sk explanation
dashboard d#dashboard_id1 w#dashboard_id1
dashboard d#dashboard_id2 w#dashboard_id2
widget [d#dashboard_id1, d#dashboard_id2] w#widget_id power of MongoDB arrays

{pk: d#dashboard_id1} will yield dashboard1 and widget records

{pk: d#dashboard_id2} will yield dashboard1 and widget records


PK, SK with type prefixes

if we are sure no widget will be reused in other dashboards, we can ignore this part.

note the usage of type prefixed at pk and sk, with it we can do some clever sorting. for example if one widget was created before a dashboard record and we want to reuse it, if we only use default mongo id in pk and sk, we could have mixed order in response:

type pk sk
widget 123456 000000
dashboard 123456 111111
widget 123456 222222

{pk: 123456}, {sortBy: sk ascending} will give us first the widget then the dashboard and again another widget, it's hard to do pagination.

when we prefix the ids

type pk sk
widget d#123456 w#000000
dashboard d#123456 d#111111
widget d#123456 w#222222

{pk: d#123456}, {sortBy: sk ascending} will always first give us one dashboard record and we can be sure in the later pages we will only get widget.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment