Search code examples
pythonormsqlalchemypython-elixir

How to make customizable "order by" for many-to-one relation to itself in Elixir or SQLAlchemy?


We have entity Node:

class Node(Entity):
    parent = ManyToOne('Node')
    children = OneToMany('Node')

When we query like this:

nodes = (
    Node.query
    .options(
        eagerload(Node.children),
    )
    .order_by(desc(Node.id))
    .all()
)

fathers = [n for n in nodes if n.parent == None]

we get pretty ordered fathers, in contrast to their children. (fathers[0].children returns unsorted list of nodes)

Almost perfect solution for this problem is to add "order_by" parameter to "children" field in Node. Something like this:

class Node(Entity):
    parent = ManyToOne('Node')
    children = OneToMany('Node', order_by='-id')

And now our children are sorted and everything fine but... What if we want to change criteria for sorting? Sometimes we want sorting by "id", sometimes -- by amount of children or something else. Now our previous solution doesn't look so good.

How can we overcome this?


Solution

  • Not sure what this Elixir syntaxes are, but here's what I'd do purely using SQLAlchemy. I'd make a function that calls the children not by your default method:

    class Node(...):
        def get_children(self, order='new'):
            if order == 'new':
                orderby = Node.created.desc()
            elif order == 'old':
                orderby = Node.created.asc()
            return DBSession.query(Node).filter(Node.parent_id == self.id).order_by(orderby).all()