'Maps vs Objects vs Arrays for core data structure in React app with document database
My app aims to allow communal viewing+editing of what are essentially tables. It's a react app (with typescript), so being useable as react component state is relevant, and using a document database (pouchDB+couchDB specifically), so being compact and serializable/deserializable as JSON is important. Performance, error tolerance, and useability are big considerations for my data structure.
The tables are basically:
- Usually a few dozen rows of maybe a dozen columns each
- Rows have unique IDs and store multiple columns. Rows are sometimes reordered.
- Columns have unique IDs which are common across rows, some columns may be empty. Columns are inserted, deleted, and compared more often than rows.
- Changes are stored as the delta for a single row's column
- "Conflicts" aren't stored in the database, but are used at runtime to describe two conflicting changes to the same row's column
I'd been representing this data like this (just an example, it's not actually about shapes):
[
{rowID: "square",
data: [
{columnID: "corners", value: 4},
{columnID: "lineType", value: "straight"}
]
},
{rowID: "happy_face",
data: [
{columnID: "corners", value: 0},
{columnID: "lineType", value: "curved"},
{columnID: "emotion", value: "happy"}
]
}
]
Changes and conflicts are basically structured the same as above, the values they store are just different. I'm wondering if I should switch from the above structure to...
Objects
RowID/ColumnID become the key in an object, and value becomes its value, like such:
{
square: {
corners: 4,
lineType: "straight"
},
happy_face: {
corners: 0,
lineType: "curved",
emotion: "happy"
}
}
Pros
- Less storage, less data over the network
- Keys must be unique, no risk of two rows/columns with same ID
- Instant n(1) property access
Cons
- Less flexible if I want to add other properties to rows or columns
- Hard to reorder (matters for rows, not columns)
- Less easily iterable
- Must iterate to get length
Maps
ES6 maps cannot actually be stored in couchDB; thus I would store them as arrays of pairs like that given to the Map() constructor, or which is obtained from Object.entries():
[
["square", [
["corners", 4],
["lineType", "straight"]
]],
["happy_face", [
["corners", 0],
["lineType", "curved"],
["emotion", "happy"]
]]
]
The above would be deserialized and turned into a nested map of maps, the outer map indexed by rowID, the inner maps by columnID.
Pros
- Every Pro mentioned above for Objects, plus...
- Can use a custom child Map class with overriden setters/getters for data validation or extra utility functions
- More performant iteration, length calculation, and insertion/deletion
Cons
- Must convert to/from array when reading/writing from DB
- Slightly tricky to use as React state
I don't want to optimize pre-emptively, but I would like to choose an appropriate data structure up front. Being flexible and less error-prone are also good. Additionally, rows and columns could use different structures. So, any recommendations, or considerations I've missed?
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
