diff --git a/CHANGELOG.md b/CHANGELOG.md index b509004..efc1c3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,25 @@ # CHANGELOG -### *??* (Unreleased) +### **0.2.0** (December 12 2022) -* Improves performance of the `limit` argument by offloading the result-limiting behavior to `grandiso`. +> Lots of great new language support by @khaole88, thank you!! -### 0.1.1 (October 1 2021) +#### Performance + +- Improves performance of the `limit` argument by offloading the result-limiting behavior to `grandiso`. + +#### Features + +- Add behavior for disconnected matches of multiple graph components (#17, thanks @khaole88!) +- Add support for anonymous nodes (#16, thanks @khaole88!) +- Support chained edges like `(A)-[]->(B)-[]-(C)` (#15, thanks @khaole88!) +- Support backwards edges (#14, thanks @khaole88!) +- Support `NULL` and the `is` operator in queriy `WHERE` and property queries (#13, thanks @khaole88!) + +### **0.1.1** (October 1 2021) > This version adds support for node-only matches. -### 0.1.0 (March 23 2021) +### **0.1.0** (March 23 2021) > This version adds initial support for querying networkx-flavored graphs with the Cypher query language. diff --git a/README.md b/README.md index adbd0b9..0913ca2 100644 --- a/README.md +++ b/README.md @@ -49,8 +49,7 @@ G.nx.add_edge("B", "C") G.nx.add_edge("C", "A") GrandCypher(G.nx).run(""" -MATCH (A)-[]->(B) -MATCH (B)-[]->(C) +MATCH (A)-[]->(B)-[]->(C) MATCH (C)-[]->(A) WHERE A.foo == "bar" @@ -61,24 +60,25 @@ RETURN # Feature Parity -| Feature | Support | | -| ------------------------------------------ | ------- | --- | -| Multiple `MATCH` clauses | ✅ | | -| `WHERE`-clause filtering on nodes | ✅ | | -| Anonymous `-[]-` edges | ✅ | | -| `LIMIT` | ✅ | | -| `SKIP` | ✅ | | -| Node/edge attributes with `{}` syntax | ✅ | | -| `WHERE`-clause filtering on edges | ✅ | | -| Named `-[]-` edges | ✅ | | -| Boolean Arithmetic (`AND`/`OR`) | 🛣 | | -| `OPTIONAL MATCH` | 🛣 | | -| Chained `()-[]->()-[]->()` edges | 🛣 | | -| Backwards `()<-[]-()` edges | 🛣 | | -| Undirected `()-[]-()` edges | 🛣 | | -| `(:Type)` node-types | 🛣 | | -| `[:Type]` edge-types | 🛣 | | -| Graph mutations (e.g. `DELETE`, `SET`,...) | 🔴 | | +| Feature | Support | | +| ------------------------------------------ | -------------------- | --- | +| Multiple `MATCH` clauses | ✅ | | +| `WHERE`-clause filtering on nodes | ✅ | | +| Anonymous `-[]-` edges | ✅ | | +| `LIMIT` | ✅ | | +| `SKIP` | ✅ | | +| Node/edge attributes with `{}` syntax | ✅ | | +| `WHERE`-clause filtering on edges | ✅ | | +| Named `-[]-` edges | ✅ | | +| Chained `()-[]->()-[]->()` edges | ✅ Thanks @khaole88! | | +| Backwards `()<-[]-()` edges | ✅ Thanks @khaole88! | | +| Anonymous `()` nodes | ✅ Thanks @khaole88! | | +| Boolean Arithmetic (`AND`/`OR`) | 🛣 | | +| `OPTIONAL MATCH` | 🛣 | | +| Undirected `()-[]-()` edges | 🛣 | | +| `(:Type)` node-types | 🛣 | | +| `[:Type]` edge-types | 🛣 | | +| Graph mutations (e.g. `DELETE`, `SET`,...) | 🔴 | | | | | | | -------------- | -------------- | ---------------- | @@ -90,17 +90,17 @@ If this tool is helpful to your research, please consider citing it with: ```bibtex # https://doi.org/10.1038/s41598-021-91025-5 -@article{Matelsky_Motifs_2021, +@article{Matelsky_Motifs_2021, title={{DotMotif: an open-source tool for connectome subgraph isomorphism search and graph queries}}, - volume={11}, - ISSN={2045-2322}, - url={http://dx.doi.org/10.1038/s41598-021-91025-5}, - DOI={10.1038/s41598-021-91025-5}, - number={1}, - journal={Scientific Reports}, - publisher={Springer Science and Business Media LLC}, + volume={11}, + ISSN={2045-2322}, + url={http://dx.doi.org/10.1038/s41598-021-91025-5}, + DOI={10.1038/s41598-021-91025-5}, + number={1}, + journal={Scientific Reports}, + publisher={Springer Science and Business Media LLC}, author={Matelsky, Jordan K. and Reilly, Elizabeth P. and Johnson, Erik C. and Stiso, Jennifer and Bassett, Danielle S. and Wester, Brock A. and Gray-Roncal, William}, - year={2021}, + year={2021}, month={Jun} } ``` diff --git a/grandcypher/__init__.py b/grandcypher/__init__.py index c22d565..8174646 100644 --- a/grandcypher/__init__.py +++ b/grandcypher/__init__.py @@ -70,7 +70,7 @@ limit_clause : "limit"i NUMBER skip_clause : "skip"i NUMBER - + ?entity_id : CNAME | CNAME "." CNAME @@ -106,14 +106,14 @@ start="start", ) -__version__ = "0.1.1" +__version__ = "0.2.0" _ALPHABET = string.ascii_lowercase + string.digits def shortuuid(k=4) -> str: - return ''.join(random.choices(_ALPHABET, k=k)) + return "".join(random.choices(_ALPHABET, k=k)) class _GrandCypherTransformer(Transformer): @@ -246,7 +246,9 @@ def _get_true_matches(self): else: raise IndexError(f"Entity {host_entity_id} not in graph.") val = self._OP( - operator, self._get_entity_from_host(*host_entity_id), value, + operator, + self._get_entity_from_host(*host_entity_id), + value, ) if val != should_be: should_include = False @@ -257,7 +259,10 @@ def _get_true_matches(self): def _get_structural_matches(self): if not self._matches: matches = [] - for motif in (self._motif.subgraph(c) for c in nx.weakly_connected_components(self._motif)): + for motif in ( + self._motif.subgraph(c) + for c in nx.weakly_connected_components(self._motif) + ): _matches = grandiso.find_motifs( motif, self._target_graph, @@ -281,7 +286,7 @@ def right_edge_match(self, edge_name): if not edge_name: return ("", "r") return (edge_name[0], "r") - + def left_edge_match(self, edge_name): if not edge_name: return ("", "l") @@ -304,8 +309,8 @@ def match_clause(self, match_clause: tuple): # This is just a node match: self._motif.add_node(match_clause[0].value) return - for start in range(0, len(match_clause)-2, 2): - (u, (g, d), v) = match_clause[start:start+3] + for start in range(0, len(match_clause) - 2, 2): + (u, (g, d), v) = match_clause[start : start + 3] if d == "r": pass elif d == "l": @@ -350,7 +355,7 @@ def op_gte(self, _): def op_lte(self, _): return _OPERATORS["<="] - + def op_is(self, _): return _OPERATORS["is"] diff --git a/setup.py b/setup.py index a8014b1..b66255d 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ setuptools.setup( name="grand-cypher", - version="0.1.1", + version="0.2.0", author="Jordan Matelsky", author_email="opensource@matelsky.com", description="Query Grand graphs using Cypher",