dash14 / v-network-graph

An interactive network graph visualization component for Vue 3
https://dash14.github.io/v-network-graph/
MIT License
485 stars 44 forks source link

[data structure design] Why don't we use array to store nodes and ref them as array index? #73

Closed Luciennnnnnn closed 1 year ago

Luciennnnnnn commented 2 years ago

Hi, @dash14. I have some data structure design choices questions.

I have to store graph data and configuration into MongoDB, but v-network-graph prefers an object attribute indexed access other than using array index, and this would have high space consumption and low processing speed. See this link for details: discussion.

Why does v-network-graph prefer using object attributes currently? I think we can refer to node use array index conveniently. Can we change to an array-based data structure?

dash14 commented 2 years ago

Hi @LuoXin-s, Thank you for your question.

Since nodes, edges, and paths have a reference relationship, their IDs should not change in principle. If nodes and edges are treated as arrays and the index of an element is used as an ID, inserting or deleting a node or edge in the middle of an array will change the index and break the reference relationship.

There is no problem when nodes and edges have not changed since the graph was created, or when there are only additions and deletions to the end of the array. While there may be such applications, this library has designed its structure for applications that insert/delete objects.

If arrays are better than objects in MongoDB, you might want to convert the structure before library input or before persistence to MongoDB.

Below is an example of converting from array structure to object structure for the library. It may be used computed if necessary.

// nodes
const nodeArray = [
  { name: "N1" },
  { name: "N2" },
  { name: "N3" },
  { name: "N4" },
]
const nodes: Nodes = Object.fromEntries(Object.entries(nodeArray))

// edges
const edgeArray = [
  { name: "edge1", source: 0, target: 1 },
  { name: "edge2", source: 1, target: 2 },
  { name: "edge3", source: 1, target: 3 },
]
const edges: Edges = Object.fromEntries(
  Object.entries(edgeArray).map(([id, e]) => [
    id,
    { name: e.name, source: String(e.source), target: String(e.target) },
  ])
)

// paths
const pathArray = [
  { edges: [0, 1] },
  { edges: [0, 2] },
]
const paths: Paths = Object.fromEntries(
  Object.entries(pathArray).map(([id, { edges }]) => [id, { edges: edges.map(e => String(e)) }])
)

// node positions
const nodePositionArray = [
  { x: 0, y: 0 },
  { x: 80, y: 80 },
  { x: 0, y: 160 },
  { x: 240, y: 80 },
]
const layouts: Layouts = {
  nodes: Object.fromEntries(Object.entries(nodePositionArray)),
}

Best Regards

Luciennnnnnn commented 2 years ago

Hi, @dash14. Thanks for your quick response. It seems we better do some conversion between two ends. I'll try it later and respond in there if there are any further problems.

dash14 commented 1 year ago

I close this issue for now. If you have any questions, please re-open this or open a new issue.