diff --git a/CHANGELOG.md b/CHANGELOG.md index b0f84c6804..3cb1419f31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - **GFQL relationship-type adjacency sidecars** (#2184): `gfql_index_edges(..., type_column=..., type_values=...)` explicitly builds forward and reverse adjacency indexes for selected string or integer relationship values. Matching queries can narrow candidate edge rows while retaining the full edge predicate and canonical results; queries without a live sidecar use ordinary adjacency. Sidecars are built at graph setup, share neighbor arrays with ordinary indexes, and appear as `typed:` rows with incremental CSR bytes in `show_indexes()`. Typed options are keyword-only. cuDF builds may add overhead on dense-community shapes, and sidecars must be rebuilt after rebinding or changing edges. +- **GFQL node-type wavefront segments**: `gfql_index_node_types(..., type_column=..., type_values=...)` builds node row-position segments for selected scalar types or Boolean labels. Matching seeded wavefront hops can narrow source and destination candidates while retaining canonical node filters and results; queries without a live segment use the ordinary paths. Node segments are built at graph setup and appear as `typed_node:` `node_type_segment` rows in `show_indexes()`; selective drop supports all segments, one column, or one segment. + - **GFQL Cypher aggregates over relationship rows**: in a single required `MATCH`, aggregates such as `MATCH (a)-[r]->(b) RETURN a, count(*), sum(r.w), collect(b.id)` run on per-path binding rows, so group keys and arguments can reference any node or relationship alias, including `DISTINCT`, post-aggregate arithmetic (`count(b) + 1`) and multi-alias keys. These shapes previously raised unsupported-query errors. ### Fixed diff --git a/bin/test-polars.sh b/bin/test-polars.sh index 895d79a87c..517b3922e6 100755 --- a/bin/test-polars.sh +++ b/bin/test-polars.sh @@ -193,6 +193,7 @@ POLARS_TEST_FILES=( graphistry/tests/compute/gfql/test_unseeded_binding_limit.py graphistry/tests/compute/gfql/index/test_indexed_bindings.py graphistry/tests/compute/gfql/index/test_typed_adjacency.py + graphistry/tests/compute/gfql/index/test_node_type_segments.py graphistry/tests/compute/gfql/index/test_indexed_bindings_membership_seed.py graphistry/tests/compute/gfql/index/test_index_ddl_in_one_call.py graphistry/tests/compute/gfql/cypher/test_in_list_seeds_the_pattern.py diff --git a/docs/source/gfql/indexing.rst b/docs/source/gfql/indexing.rst index 0bfa191f7e..b8e3f35c9b 100644 --- a/docs/source/gfql/indexing.rst +++ b/docs/source/gfql/indexing.rst @@ -200,6 +200,30 @@ The ``typed:`` rows in ``show_indexes()`` report incremental CSR bytes; they share the ordinary adjacency's neighbor arrays. Build for the engine used by the query, and rebuild after binding a new edge frame or changing edges in place. +Select node types or labels +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For repeated hops that filter nodes by type or label, build row-position sidecars +the same way as for relationship types (see the previous section): +``gfql_index_node_types(type_column=..., type_values=...)`` is the node-frame dual +of ``gfql_index_edges``. A scalar column partitions rows; a Boolean +``label__