Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal to filter on generic cypher expression #343

Open
stevenvdr opened this issue Jun 1, 2018 · 5 comments
Open

Proposal to filter on generic cypher expression #343

stevenvdr opened this issue Jun 1, 2018 · 5 comments

Comments

@stevenvdr
Copy link

For a project I wanted to order my nodes based on the distance from a certain point. For realising this in neomodel I have created my own NodeSet and QueryBuilder to support this. Is this functionality that would be wanted in the neomodel package. If so I could create a Pull request for this.

Below is the snippet to support a new function order_by_cypher that allows to use any cypher expression to use in order_by. The NodeSet adds the cypher expression to self._order_by after which it is picked up by the QueryBuilder when doing build_order_by (if the property exists on the model it will use the previous behaviour, if not it will use the cypher literal).

class OrderByCypherNode(StructuredNode):
    """
    Class that overrules the used NodeSet, so the order_by_cypher can
    be used
    """

    @classproperty
    def nodes(cls):
        """
        Returns a NodeSet object representing all nodes of the classes label
        :return: NodeSet
        :rtype: NodeSet
        """
        return OrderByCypherNodeSet(cls)


class OrderByCypherQueryBuilder(QueryBuilder):
    """ Querybuilder with support for generic cypher order_by statements """

    def build_order_by(self, ident, source):
        if '?' in source._order_by:
            self._ast['with'] = '{}, rand() as r'.format(ident)
            self._ast['order_by'] = 'r'
        else:
            self._ast['order_by'] = ['{}.{}'.format(ident, p)
                                     if hasattr(source.source_class, p)
                                     else p.format(ident=ident)
                                     for p in source._order_by]


class OrderByCypherNodeSet(NodeSet):
    """ NodeSet with support for generic cypher order_by statements """

    query_cls = OrderByCypherQueryBuilder

    def order_by_cypher(self, cypher):
        if not hasattr(self, '_order_by'):
            self._order_by = []
        self._order_by.append(cypher)

        return self
@oikonomou
Copy link

@stevenvdr I have a similar situation where I want to fetch ordered objects by a given list of custom uuids.
There is a way when using plain cypher but, through neomodel, I see that custom QueryBuilder needs to be implemented.
Have you found any other way of doing such work in neomodel or is this the only way?

@stevenvdr
Copy link
Author

I've found the snippet that I posted to be the easiest solution. There might be other ways, but I haven't checked as the snippet did what I needed (which was sort by distance to a certain point)

@oikonomou
Copy link

@stevenvdr thanks for the advice! I think I will start implementing an extended QueryBuilder, too.

@aanastasiou
Copy link
Collaborator

@stevenvdr , @oikonomou Any updates on this?

@mariusconjeaud
Copy link
Collaborator

@owinogradow Could this be interesting to extend what you did on the ordering in the extension ?

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

No branches or pull requests

4 participants