Skip to main content

nodedb_lite/nodedb/core/ops/
spatial.rs

1// SPDX-License-Identifier: Apache-2.0
2
3//! Spatial index public API: insert, delete, bbox search, nearest-neighbor.
4
5use crate::nodedb::core::types::NodeDbLite;
6use crate::nodedb::lock_ext::LockExt;
7use crate::storage::engine::StorageEngine;
8
9impl<S: StorageEngine> NodeDbLite<S> {
10    // ── Spatial public API ────────────────────────────────────────────────────
11
12    /// Index a geometry in a collection's spatial index.
13    ///
14    /// `field` identifies which geometry field is being indexed (allows a
15    /// collection to carry multiple spatial fields).  If the document was
16    /// previously indexed under the same `(collection, doc_id)`, the old entry
17    /// is replaced (upsert semantics).
18    pub fn spatial_insert(
19        &self,
20        collection: &str,
21        field: &str,
22        doc_id: &str,
23        geometry: &nodedb_types::geometry::Geometry,
24    ) {
25        let mut spatial = self.spatial.lock_or_recover();
26        spatial.index_document(collection, field, doc_id, geometry);
27        drop(spatial);
28        #[cfg(not(target_arch = "wasm32"))]
29        if let Some(q) = &self.spatial_outbound {
30            q.stage_insert(collection, field, doc_id, geometry);
31        }
32    }
33
34    /// Remove a document's geometry from the spatial index.
35    pub fn spatial_delete(&self, collection: &str, field: &str, doc_id: &str) {
36        let mut spatial = self.spatial.lock_or_recover();
37        spatial.remove_document(collection, field, doc_id);
38        drop(spatial);
39        #[cfg(not(target_arch = "wasm32"))]
40        if let Some(q) = &self.spatial_outbound {
41            q.stage_delete(collection, field, doc_id);
42        }
43    }
44
45    /// Bounding-box range search: returns all doc entry IDs whose bbox
46    /// intersects the query rectangle.
47    pub fn spatial_search_bbox(
48        &self,
49        collection: &str,
50        field: &str,
51        query: &nodedb_types::BoundingBox,
52    ) -> Vec<nodedb_spatial::rtree::RTreeEntry> {
53        let spatial = self.spatial.lock_or_recover();
54        spatial
55            .search(collection, field, query)
56            .into_iter()
57            .cloned()
58            .collect()
59    }
60
61    /// Nearest-neighbor search: returns the `k` closest spatial entries to
62    /// the given `(lng, lat)` point.
63    pub fn spatial_nearest(
64        &self,
65        collection: &str,
66        field: &str,
67        lng: f64,
68        lat: f64,
69        k: usize,
70    ) -> Vec<nodedb_spatial::rtree::NnResult> {
71        let spatial = self.spatial.lock_or_recover();
72        spatial.nearest(collection, field, lng, lat, k)
73    }
74}