pub trait GraphStorage {
Show 81 methods
// Required methods
fn contains_node(&self, id: NodeId) -> bool;
fn node(&self, id: NodeId) -> Option<NodeRecord>;
fn all_node_ids(&self) -> Vec<NodeId> ⓘ;
fn node_ids_by_label(&self, label: &str) -> Vec<NodeId> ⓘ;
fn contains_relationship(&self, id: RelationshipId) -> bool;
fn relationship(&self, id: RelationshipId) -> Option<RelationshipRecord>;
fn all_rel_ids(&self) -> Vec<RelationshipId> ⓘ;
fn rel_ids_by_type(&self, rel_type: &str) -> Vec<RelationshipId> ⓘ;
fn relationship_endpoints(
&self,
id: RelationshipId,
) -> Option<(NodeId, NodeId)>;
fn expand_ids(
&self,
node_id: NodeId,
direction: Direction,
types: &[String],
) -> Vec<(RelationshipId, NodeId)>;
fn all_labels(&self) -> Vec<String>;
fn all_relationship_types(&self) -> Vec<String>;
// Provided methods
fn try_for_each_expand_id<F, E>(
&self,
node_id: NodeId,
direction: Direction,
types: &[String],
visit: F,
) -> Result<(), E>
where F: FnMut(RelationshipId, NodeId) -> Result<(), E>,
Self: Sized { ... }
fn with_node<F, R>(&self, id: NodeId, f: F) -> Option<R>
where F: FnOnce(&NodeRecord) -> R,
Self: Sized { ... }
fn with_relationship<F, R>(&self, id: RelationshipId, f: F) -> Option<R>
where F: FnOnce(&RelationshipRecord) -> R,
Self: Sized { ... }
fn has_node(&self, id: NodeId) -> bool { ... }
fn has_relationship(&self, id: RelationshipId) -> bool { ... }
fn node_count(&self) -> usize { ... }
fn relationship_count(&self) -> usize { ... }
fn all_nodes(&self) -> Vec<NodeRecord> { ... }
fn nodes_by_label(&self, label: &str) -> Vec<NodeRecord> { ... }
fn all_relationships(&self) -> Vec<RelationshipRecord> { ... }
fn relationships_by_type(&self, rel_type: &str) -> Vec<RelationshipRecord> { ... }
fn relationship_ids_of(
&self,
node_id: NodeId,
direction: Direction,
) -> Vec<RelationshipId> ⓘ { ... }
fn outgoing_relationships(&self, node_id: NodeId) -> Vec<RelationshipRecord> { ... }
fn incoming_relationships(&self, node_id: NodeId) -> Vec<RelationshipRecord> { ... }
fn relationships_of(
&self,
node_id: NodeId,
direction: Direction,
) -> Vec<RelationshipRecord> { ... }
fn degree(&self, node_id: NodeId, direction: Direction) -> usize { ... }
fn is_isolated(&self, node_id: NodeId) -> bool { ... }
fn expand(
&self,
node_id: NodeId,
direction: Direction,
types: &[String],
) -> Vec<(RelationshipRecord, NodeRecord)> { ... }
fn expand_detailed(
&self,
node_id: NodeId,
direction: Direction,
types: &[String],
) -> Vec<ExpandedRelationship> { ... }
fn neighbors(
&self,
node_id: NodeId,
direction: Direction,
types: &[String],
) -> Vec<NodeRecord> { ... }
fn node_has_label(&self, node_id: NodeId, label: &str) -> bool
where Self: Sized { ... }
fn node_labels(&self, node_id: NodeId) -> Option<Vec<String>>
where Self: Sized { ... }
fn node_properties(&self, node_id: NodeId) -> Option<Properties>
where Self: Sized { ... }
fn node_property(&self, node_id: NodeId, key: &str) -> Option<PropertyValue>
where Self: Sized { ... }
fn relationship_type(&self, rel_id: RelationshipId) -> Option<String>
where Self: Sized { ... }
fn relationship_properties(
&self,
rel_id: RelationshipId,
) -> Option<Properties>
where Self: Sized { ... }
fn relationship_property(
&self,
rel_id: RelationshipId,
key: &str,
) -> Option<PropertyValue>
where Self: Sized { ... }
fn relationship_source(&self, rel_id: RelationshipId) -> Option<NodeId> { ... }
fn relationship_target(&self, rel_id: RelationshipId) -> Option<NodeId> { ... }
fn other_node(
&self,
rel_id: RelationshipId,
node_id: NodeId,
) -> Option<NodeId> { ... }
fn has_label_name(&self, label: &str) -> bool { ... }
fn has_relationship_type_name(&self, rel_type: &str) -> bool { ... }
fn all_node_property_keys(&self) -> Vec<String>
where Self: Sized { ... }
fn all_relationship_property_keys(&self) -> Vec<String>
where Self: Sized { ... }
fn all_property_keys(&self) -> Vec<String>
where Self: Sized { ... }
fn has_property_key(&self, key: &str) -> bool
where Self: Sized { ... }
fn label_property_keys(&self, label: &str) -> Vec<String>
where Self: Sized { ... }
fn rel_type_property_keys(&self, rel_type: &str) -> Vec<String>
where Self: Sized { ... }
fn label_has_property_key(&self, label: &str, key: &str) -> bool
where Self: Sized { ... }
fn rel_type_has_property_key(&self, rel_type: &str, key: &str) -> bool
where Self: Sized { ... }
fn find_nodes_by_property(
&self,
label: Option<&str>,
key: &str,
value: &PropertyValue,
) -> Vec<NodeRecord>
where Self: Sized { ... }
fn find_node_ids_by_property(
&self,
label: Option<&str>,
key: &str,
value: &PropertyValue,
) -> Vec<NodeId> ⓘ
where Self: Sized { ... }
fn find_relationships_by_property(
&self,
rel_type: Option<&str>,
key: &str,
value: &PropertyValue,
) -> Vec<RelationshipRecord>
where Self: Sized { ... }
fn find_relationship_ids_by_property(
&self,
rel_type: Option<&str>,
key: &str,
value: &PropertyValue,
) -> Vec<RelationshipId> ⓘ
where Self: Sized { ... }
fn node_exists_with_label_and_property(
&self,
label: &str,
key: &str,
value: &PropertyValue,
) -> bool
where Self: Sized { ... }
fn relationship_exists_with_type_and_property(
&self,
rel_type: &str,
key: &str,
value: &PropertyValue,
) -> bool
where Self: Sized { ... }
fn list_indexes(&self) -> Vec<IndexDefinition> { ... }
fn get_index(&self, _name: &str) -> Option<IndexDefinition> { ... }
fn fulltext_search(&self, _name: &str, _query: &str) -> Vec<(u64, f64)> { ... }
fn list_constraints(&self) -> Vec<ConstraintDefinition> { ... }
fn get_constraint(&self, _name: &str) -> Option<ConstraintDefinition> { ... }
fn check_node_create_against_constraints(
&self,
_labels: &[String],
_properties: &Properties,
) -> Result<(), String> { ... }
fn check_relationship_create_against_constraints(
&self,
_rel_type: &str,
_properties: &Properties,
) -> Result<(), String> { ... }
fn check_node_set_property_against_constraints(
&self,
_node_id: NodeId,
_key: &str,
_value: &PropertyValue,
) -> Result<(), String> { ... }
fn check_node_remove_property_against_constraints(
&self,
_node_id: NodeId,
_key: &str,
) -> Result<(), String> { ... }
fn check_node_replace_properties_against_constraints(
&self,
_node_id: NodeId,
_properties: &Properties,
) -> Result<(), String> { ... }
fn check_relationship_set_property_against_constraints(
&self,
_rel_id: RelationshipId,
_key: &str,
_value: &PropertyValue,
) -> Result<(), String> { ... }
fn check_relationship_remove_property_against_constraints(
&self,
_rel_id: RelationshipId,
_key: &str,
) -> Result<(), String> { ... }
fn check_relationship_replace_properties_against_constraints(
&self,
_rel_id: RelationshipId,
_properties: &Properties,
) -> Result<(), String> { ... }
fn check_node_add_label_against_constraints(
&self,
_node_id: NodeId,
_label: &str,
) -> Result<(), String> { ... }
fn graph_stats(&self) -> GraphStats { ... }
fn node_text_candidates(
&self,
_label: &str,
_property: &str,
_query: &str,
) -> Option<Vec<NodeId>> { ... }
fn node_range_candidates(
&self,
_label: &str,
_property: &str,
_lo: Option<&PropertyValue>,
_hi: Option<&PropertyValue>,
) -> Option<Vec<NodeId>> { ... }
fn node_point_within_bbox(
&self,
_label: &str,
_property: &str,
_ll: (f64, f64),
_ur: (f64, f64),
) -> Option<Vec<NodeId>> { ... }
fn node_point_within_distance(
&self,
_label: &str,
_property: &str,
_center: (f64, f64),
_max_distance: f64,
) -> Option<Vec<NodeId>> { ... }
fn relationship_text_candidates(
&self,
_rel_type: &str,
_property: &str,
_query: &str,
) -> Option<Vec<RelationshipId>> { ... }
fn relationship_range_candidates(
&self,
_rel_type: &str,
_property: &str,
_lo: Option<&PropertyValue>,
_hi: Option<&PropertyValue>,
) -> Option<Vec<RelationshipId>> { ... }
fn relationship_point_within_bbox(
&self,
_rel_type: &str,
_property: &str,
_ll: (f64, f64),
_ur: (f64, f64),
) -> Option<Vec<RelationshipId>> { ... }
fn relationship_point_within_distance(
&self,
_rel_type: &str,
_property: &str,
_center: (f64, f64),
_max_distance: f64,
) -> Option<Vec<RelationshipId>> { ... }
}Required Methods§
Sourcefn contains_node(&self, id: NodeId) -> bool
fn contains_node(&self, id: NodeId) -> bool
Cheap existence check. Should not clone or materialize the record.
Sourcefn node(&self, id: NodeId) -> Option<NodeRecord>
fn node(&self, id: NodeId) -> Option<NodeRecord>
Point lookup returning an owned record. Backends that can hand out
borrows should also implement BorrowedGraphStorage::node_ref and
override [with_node] to avoid clones on the hot path.
Sourcefn all_node_ids(&self) -> Vec<NodeId> ⓘ
fn all_node_ids(&self) -> Vec<NodeId> ⓘ
Enumerate every node id. Should be O(nodes) without cloning records.
Sourcefn node_ids_by_label(&self, label: &str) -> Vec<NodeId> ⓘ
fn node_ids_by_label(&self, label: &str) -> Vec<NodeId> ⓘ
Enumerate node ids carrying the given label. Implementations that keep a label index should override this.
fn contains_relationship(&self, id: RelationshipId) -> bool
fn relationship(&self, id: RelationshipId) -> Option<RelationshipRecord>
fn all_rel_ids(&self) -> Vec<RelationshipId> ⓘ
fn rel_ids_by_type(&self, rel_type: &str) -> Vec<RelationshipId> ⓘ
Sourcefn relationship_endpoints(&self, id: RelationshipId) -> Option<(NodeId, NodeId)>
fn relationship_endpoints(&self, id: RelationshipId) -> Option<(NodeId, NodeId)>
Endpoint pair (src, dst) for a relationship. Required because
traversal uses it on hot paths; a backend that stores endpoints
alongside the id index can answer this without fetching properties.
Sourcefn expand_ids(
&self,
node_id: NodeId,
direction: Direction,
types: &[String],
) -> Vec<(RelationshipId, NodeId)>
fn expand_ids( &self, node_id: NodeId, direction: Direction, types: &[String], ) -> Vec<(RelationshipId, NodeId)>
Expand a node’s incident relationships filtered by direction and (optional) types. This is the single traversal primitive; variable- length paths, degree, and adjacency helpers are all derived from it.
fn all_labels(&self) -> Vec<String>
fn all_relationship_types(&self) -> Vec<String>
Provided Methods§
Sourcefn try_for_each_expand_id<F, E>(
&self,
node_id: NodeId,
direction: Direction,
types: &[String],
visit: F,
) -> Result<(), E>
fn try_for_each_expand_id<F, E>( &self, node_id: NodeId, direction: Direction, types: &[String], visit: F, ) -> Result<(), E>
Visit expanded (relationship_id, other_node_id) pairs without
forcing backends to allocate an intermediate Vec. The default keeps the
trait easy to implement; hot backends can override it.
fn with_node<F, R>(&self, id: NodeId, f: F) -> Option<R>
fn with_relationship<F, R>(&self, id: RelationshipId, f: F) -> Option<R>
fn has_node(&self, id: NodeId) -> bool
fn has_relationship(&self, id: RelationshipId) -> bool
fn node_count(&self) -> usize
fn relationship_count(&self) -> usize
fn all_nodes(&self) -> Vec<NodeRecord>
fn nodes_by_label(&self, label: &str) -> Vec<NodeRecord>
fn all_relationships(&self) -> Vec<RelationshipRecord>
fn relationships_by_type(&self, rel_type: &str) -> Vec<RelationshipRecord>
fn relationship_ids_of( &self, node_id: NodeId, direction: Direction, ) -> Vec<RelationshipId> ⓘ
fn outgoing_relationships(&self, node_id: NodeId) -> Vec<RelationshipRecord>
fn incoming_relationships(&self, node_id: NodeId) -> Vec<RelationshipRecord>
fn relationships_of( &self, node_id: NodeId, direction: Direction, ) -> Vec<RelationshipRecord>
fn degree(&self, node_id: NodeId, direction: Direction) -> usize
fn is_isolated(&self, node_id: NodeId) -> bool
fn expand( &self, node_id: NodeId, direction: Direction, types: &[String], ) -> Vec<(RelationshipRecord, NodeRecord)>
fn expand_detailed( &self, node_id: NodeId, direction: Direction, types: &[String], ) -> Vec<ExpandedRelationship>
fn neighbors( &self, node_id: NodeId, direction: Direction, types: &[String], ) -> Vec<NodeRecord>
fn node_has_label(&self, node_id: NodeId, label: &str) -> boolwhere
Self: Sized,
fn node_labels(&self, node_id: NodeId) -> Option<Vec<String>>where
Self: Sized,
fn node_properties(&self, node_id: NodeId) -> Option<Properties>where
Self: Sized,
fn node_property(&self, node_id: NodeId, key: &str) -> Option<PropertyValue>where
Self: Sized,
fn relationship_type(&self, rel_id: RelationshipId) -> Option<String>where
Self: Sized,
fn relationship_properties(&self, rel_id: RelationshipId) -> Option<Properties>where
Self: Sized,
fn relationship_property(
&self,
rel_id: RelationshipId,
key: &str,
) -> Option<PropertyValue>where
Self: Sized,
fn relationship_source(&self, rel_id: RelationshipId) -> Option<NodeId>
fn relationship_target(&self, rel_id: RelationshipId) -> Option<NodeId>
fn other_node(&self, rel_id: RelationshipId, node_id: NodeId) -> Option<NodeId>
fn has_label_name(&self, label: &str) -> bool
fn has_relationship_type_name(&self, rel_type: &str) -> bool
fn all_node_property_keys(&self) -> Vec<String>where
Self: Sized,
fn all_relationship_property_keys(&self) -> Vec<String>where
Self: Sized,
fn all_property_keys(&self) -> Vec<String>where
Self: Sized,
fn has_property_key(&self, key: &str) -> boolwhere
Self: Sized,
fn label_property_keys(&self, label: &str) -> Vec<String>where
Self: Sized,
fn rel_type_property_keys(&self, rel_type: &str) -> Vec<String>where
Self: Sized,
fn label_has_property_key(&self, label: &str, key: &str) -> boolwhere
Self: Sized,
fn rel_type_has_property_key(&self, rel_type: &str, key: &str) -> boolwhere
Self: Sized,
fn find_nodes_by_property(
&self,
label: Option<&str>,
key: &str,
value: &PropertyValue,
) -> Vec<NodeRecord>where
Self: Sized,
fn find_node_ids_by_property(
&self,
label: Option<&str>,
key: &str,
value: &PropertyValue,
) -> Vec<NodeId> ⓘwhere
Self: Sized,
fn find_relationships_by_property(
&self,
rel_type: Option<&str>,
key: &str,
value: &PropertyValue,
) -> Vec<RelationshipRecord>where
Self: Sized,
fn find_relationship_ids_by_property(
&self,
rel_type: Option<&str>,
key: &str,
value: &PropertyValue,
) -> Vec<RelationshipId> ⓘwhere
Self: Sized,
fn node_exists_with_label_and_property(
&self,
label: &str,
key: &str,
value: &PropertyValue,
) -> boolwhere
Self: Sized,
fn relationship_exists_with_type_and_property(
&self,
rel_type: &str,
key: &str,
value: &PropertyValue,
) -> boolwhere
Self: Sized,
fn list_indexes(&self) -> Vec<IndexDefinition>
fn get_index(&self, _name: &str) -> Option<IndexDefinition>
Sourcefn fulltext_search(&self, _name: &str, _query: &str) -> Vec<(u64, f64)>
fn fulltext_search(&self, _name: &str, _query: &str) -> Vec<(u64, f64)>
Run a FULLTEXT index query against the named index. Returns
(entity_id, score) pairs sorted descending by score. Backends
without fulltext support return an empty vector; the caller is
expected to have validated that the index exists via the
catalog first.
Sourcefn list_constraints(&self) -> Vec<ConstraintDefinition>
fn list_constraints(&self) -> Vec<ConstraintDefinition>
List explicitly-declared constraints. Backends without a constraint catalog return the empty vector.
fn get_constraint(&self, _name: &str) -> Option<ConstraintDefinition>
Sourcefn check_node_create_against_constraints(
&self,
_labels: &[String],
_properties: &Properties,
) -> Result<(), String>
fn check_node_create_against_constraints( &self, _labels: &[String], _properties: &Properties, ) -> Result<(), String>
Mutation-time pre-check: would creating a node with these
labels and properties violate any registered constraint?
Default returns Ok(()) so backends without a constraint
catalog pay nothing. The in-memory backend overrides this and
the call is virtually free when the catalog is empty.
Sourcefn check_relationship_create_against_constraints(
&self,
_rel_type: &str,
_properties: &Properties,
) -> Result<(), String>
fn check_relationship_create_against_constraints( &self, _rel_type: &str, _properties: &Properties, ) -> Result<(), String>
Mutation-time pre-check for CREATE ()-[r:TYPE { ... }]->().
Sourcefn check_node_set_property_against_constraints(
&self,
_node_id: NodeId,
_key: &str,
_value: &PropertyValue,
) -> Result<(), String>
fn check_node_set_property_against_constraints( &self, _node_id: NodeId, _key: &str, _value: &PropertyValue, ) -> Result<(), String>
Mutation-time pre-check: would setting key = value on this
node violate any registered constraint? Default Ok(()).
Sourcefn check_node_remove_property_against_constraints(
&self,
_node_id: NodeId,
_key: &str,
) -> Result<(), String>
fn check_node_remove_property_against_constraints( &self, _node_id: NodeId, _key: &str, ) -> Result<(), String>
Mutation-time pre-check: would removing key on this node
violate an existence / key constraint? Default Ok(()).
Sourcefn check_node_replace_properties_against_constraints(
&self,
_node_id: NodeId,
_properties: &Properties,
) -> Result<(), String>
fn check_node_replace_properties_against_constraints( &self, _node_id: NodeId, _properties: &Properties, ) -> Result<(), String>
Mutation-time pre-check: would replacing all properties on this
node leave it in violation of any registered constraint? Default
Ok(()).
Sourcefn check_relationship_set_property_against_constraints(
&self,
_rel_id: RelationshipId,
_key: &str,
_value: &PropertyValue,
) -> Result<(), String>
fn check_relationship_set_property_against_constraints( &self, _rel_id: RelationshipId, _key: &str, _value: &PropertyValue, ) -> Result<(), String>
Mutation-time pre-check: equivalent for relationship property writes.
fn check_relationship_remove_property_against_constraints( &self, _rel_id: RelationshipId, _key: &str, ) -> Result<(), String>
Sourcefn check_relationship_replace_properties_against_constraints(
&self,
_rel_id: RelationshipId,
_properties: &Properties,
) -> Result<(), String>
fn check_relationship_replace_properties_against_constraints( &self, _rel_id: RelationshipId, _properties: &Properties, ) -> Result<(), String>
Mutation-time pre-check: would replacing all properties on this
relationship leave it in violation of any registered constraint?
Default Ok(()).
Sourcefn check_node_add_label_against_constraints(
&self,
_node_id: NodeId,
_label: &str,
) -> Result<(), String>
fn check_node_add_label_against_constraints( &self, _node_id: NodeId, _label: &str, ) -> Result<(), String>
Mutation-time pre-check: would adding label to this node
activate a constraint the node currently violates?
Sourcefn graph_stats(&self) -> GraphStats
fn graph_stats(&self) -> GraphStats
Cardinality snapshot used by the cost model. Backends without
per-label / per-type indexes return GraphStats::default(),
which the planner treats as “no information available”.
Sourcefn node_text_candidates(
&self,
_label: &str,
_property: &str,
_query: &str,
) -> Option<Vec<NodeId>>
fn node_text_candidates( &self, _label: &str, _property: &str, _query: &str, ) -> Option<Vec<NodeId>>
Trigram-index candidates for query on label.property.
Semantics:
Some(ids)→ these node ids might match (refilter required).None→ no trigram scope for(label, property); caller must fall back to a full scan.
Backends without text-index support always return None.
Sourcefn node_range_candidates(
&self,
_label: &str,
_property: &str,
_lo: Option<&PropertyValue>,
_hi: Option<&PropertyValue>,
) -> Option<Vec<NodeId>>
fn node_range_candidates( &self, _label: &str, _property: &str, _lo: Option<&PropertyValue>, _hi: Option<&PropertyValue>, ) -> Option<Vec<NodeId>>
Sorted-index candidates for a [lo, hi] range on label.property.
Both bounds are inclusive at this layer; the caller refilters with
the precise predicate inclusivity (> vs >=, < vs <=).
Returns None when no scope exists — caller falls back to scan.
Sourcefn node_point_within_bbox(
&self,
_label: &str,
_property: &str,
_ll: (f64, f64),
_ur: (f64, f64),
) -> Option<Vec<NodeId>>
fn node_point_within_bbox( &self, _label: &str, _property: &str, _ll: (f64, f64), _ur: (f64, f64), ) -> Option<Vec<NodeId>>
Spatial-index candidates inside the closed [ll, ur] 2D
bounding box. The executor refilters every id with the precise
predicate, including the z-coordinate when the indexed point
is 3D.
Sourcefn node_point_within_distance(
&self,
_label: &str,
_property: &str,
_center: (f64, f64),
_max_distance: f64,
) -> Option<Vec<NodeId>>
fn node_point_within_distance( &self, _label: &str, _property: &str, _center: (f64, f64), _max_distance: f64, ) -> Option<Vec<NodeId>>
Spatial-index candidates within max_distance of (x, y). The
candidate set is conservative — the actual great-circle /
cartesian distance check is the executor’s responsibility.
Sourcefn relationship_text_candidates(
&self,
_rel_type: &str,
_property: &str,
_query: &str,
) -> Option<Vec<RelationshipId>>
fn relationship_text_candidates( &self, _rel_type: &str, _property: &str, _query: &str, ) -> Option<Vec<RelationshipId>>
Trigram-index candidates for relationships of rel_type whose
property value matches query (substring/prefix/suffix). Mirror
of Self::node_text_candidates for relationship-target indexes.
Sourcefn relationship_range_candidates(
&self,
_rel_type: &str,
_property: &str,
_lo: Option<&PropertyValue>,
_hi: Option<&PropertyValue>,
) -> Option<Vec<RelationshipId>>
fn relationship_range_candidates( &self, _rel_type: &str, _property: &str, _lo: Option<&PropertyValue>, _hi: Option<&PropertyValue>, ) -> Option<Vec<RelationshipId>>
Sorted-index candidates for relationships of rel_type on the
closed [lo, hi] range. Mirror of Self::node_range_candidates.
Sourcefn relationship_point_within_bbox(
&self,
_rel_type: &str,
_property: &str,
_ll: (f64, f64),
_ur: (f64, f64),
) -> Option<Vec<RelationshipId>>
fn relationship_point_within_bbox( &self, _rel_type: &str, _property: &str, _ll: (f64, f64), _ur: (f64, f64), ) -> Option<Vec<RelationshipId>>
Spatial-index candidates inside the closed [ll, ur] 2D bounding
box, scoped to relationships of rel_type. Mirror of
Self::node_point_within_bbox.
Sourcefn relationship_point_within_distance(
&self,
_rel_type: &str,
_property: &str,
_center: (f64, f64),
_max_distance: f64,
) -> Option<Vec<RelationshipId>>
fn relationship_point_within_distance( &self, _rel_type: &str, _property: &str, _center: (f64, f64), _max_distance: f64, ) -> Option<Vec<RelationshipId>>
Spatial-index candidates within max_distance of (x, y),
scoped to relationships of rel_type. Mirror of
Self::node_point_within_distance.