👽 How do you do a dynamic "list of lists" or otherwise solve the following problem

Here is my beautiful code:

    def addArrow(self, arrow):
        cql = """
        MATCH (s),(t)
        WHERE id(s)=$srcid AND id(t)=$tarid 
        CREATE (s)-[r:Morphism {labels:$labels, labelposx:$labelposx, labelposy:$labelposy, 
        tailstyle:$tailstyle, headcount:$headcount, pendash:$pendash, penwidth:$penwidth, pencol:$pencol, 
        pos0:$pos0, pos1:$pos1, pos2:$pos2, pos3:$pos3, pos:$pos}]->(t) 
        RETURN id(r)
        """
        points = arrow.controlPoints()
        try:
            with self._driver.session() as session:
                id = session.run(cql, parameters={
                                     'labels': [label.text() for label in arrow.labels()],
                                     'labelposx': [label.pos().x() for label in arrow.labels()],
                                     'labelposy': [label.pos().y() for label in arrow.labels()],
                                     'srcid': arrow.sourceNode().databaseID(),
                                     'tarid': arrow.targetNode().databaseID(),
                                     'tailstyle': arrow.tailStyle(),
                                     'headcount': arrow.numberOfHeads(),
                                     'pendash': arrow.pen().style(),
                                     'penwidth': arrow.pen().widthF(),
                                     'pencol': colorToList(arrow.pen().color()),
                                     'pos0': pointToList(points[0].pos()),
                                     'pos1': pointToList(points[1].pos()),
                                     'pos2': pointToList(points[2].pos()),
                                     'pos3': pointToList(points[3].pos()),
                                     'pos': pointToList(arrow.pos()),
                                     }).single().value()
            arrow.setDatabaseID(id)
        except Exception as e:
            Error(str(e)).exec_()
            if __debug__:
                raise e
                                 'labels': [label.text() for label in arrow.labels()],
                                 'labelposx': [label.pos().x() for label in arrow.labels()],
                                 'labelposy': [label.pos().y() for label in arrow.labels()],

The problem is: each arrow has a list of labels, but each label has a position which is a list of floats. So as you can see I've broken it up into labelposx / labelposy so that these label lists can be dynamically updated. Is there a better way to do this such that the positions are contained with a "Label" structure? The problem now becomes worse if I want an independent color per label. Then I need labelcolorred... labelcoloralpha, which is four more lists.

Just wondering, I'm happy with the above if that's what we're limited to.

Thank you!

:banana::joy_cat:

I don't fully understand your question, it's probably also not a "newbie" one :slight_smile:

Also you're putting an awful lot on a relationship, are you sure that Morphism is not an important entity of your domain that is actually a node?

Nope, I'm wanting the Neo4j browser to reflect these "commutative diagrams in math" 1-1, so that:

  1. Easy to debug
  2. People can see that its working
  3. It would be weirder to diverge from this since a diagram is already a graph.

That's not stuff I'm doing search by although a user might want to say "All diagrams with a red node" and if I offer custom cypher queries they can do that.

The default search is going to be an exact one based on label subset or just purely structural (treated as unlabeld graphs).

Can we do something like this is what I mean:

"labels": [
{ "pos:" : [0.5, 1.0],
"color": [255, 0, 0, 255],
},
{ ... }
]

you can create that in cypher, sure

with literal maps {a:10} and lists [1,2,3]
and you can nest them either with collect: {a: collect({b:n.prop})}

or you can use map projections with pattern coprehensions

node { .prop, .*, foo:42, bar:[(node)-->(other) | other.prop]}