Search code examples
amazon-neptunegremlinpython

How to use property value to filter out vertices?


I'm trying to filter out vertices to which distance from given latitude and longitude is above max distance stored as vertex property and retrieve the ones that are not filtered. I used code from Kelvin Lawrence's book to calculate the distance using the Haversine Great Circle Distance formula. The thing is, if I pass an integer value to lte everything seems to be working fine, but I need to feed it with each traversed vertex property value. Code:

    r_deg = 0.017453293
    e_rad = 6371

    def get_points_within_distance(latitude, longitude, r_deg, e_rad):
        try:
            _result = n_graph. \
                with_side_effect("r_deg", r_deg). \
                with_side_effect("e_rad", e_rad). \
                with_side_effect("p_lat", latitude). \
                with_side_effect("p_lon", longitude). \
                V(). \
                hasLabel("point"). \
                where(
                    project("ladiff", "lodiff", "latitude", "longitude").
                    by(project("lat").by("latitude").
                        math("(lat - p_lat) * r_deg")).
                    by(project("lon").by("longitude").
                        math("(lon - p_lon) * r_deg")).
                    by("latitude").
                    by("longitude").
                    math('(sin(ladiff/2))^2 + cos(latitude*r_deg) * cos(p_lat*r_deg) * (sin(lodiff/2))^2').
                    math('e_rad * (2 * asin(sqrt(_)))').
                    is_(lte(10))
                ). \
                value_map(True). \
                to_list()
        except Exception as _e:
            LOG.error(f"Failed to retrieve points: {_e}.")
            return
        return _result

Each vertex has three properties:

  • latitude
  • longitude
  • max_distance

What I'm trying to achieve is to pass max_distance value instead of 10.


Solution

  • You'll need to use the where()-by() approach here. Instead of using the where() as part of the calculation, we'll use an as() label to bookmark our starting vertex. Then perform the distance calculation and use the where()-by() to filter. After the where()-by(), we'll refer back to the starting vertex via a select() on the label for the traversals that passed the filter.

    n_graph. 
        with_side_effect("r_deg", r_deg). 
        with_side_effect("e_rad", e_rad). 
        with_side_effect("p_lat", latitude). 
        with_side_effect("p_lon", longitude). 
        V(). 
        hasLabel("point").
        as("startPoint").
        project("ladiff", "lodiff", "latitude", "longitude").
            by(project("lat").by("latitude").
                math("(lat - p_lat) * r_deg")).
            by(project("lon").by("longitude").
                math("(lon - p_lon) * r_deg")).
            by("latitude").
            by("longitude").
        math('(sin(ladiff/2))^2 + cos(latitude*r_deg) * cos(p_lat*r_deg) * (sin(lodiff/2))^2').
        math('e_rad * (2 * asin(sqrt(_)))').
        where(lte("startPoint")).by().by("max_distance").
        select("startPoint").
        value_map(True). 
        to_list()