0

I have a working js gremlin query for Haversine distance which I am looking to make more composable by setting constants for usage in the math step in some other way than using withSideEffect.

The necessity of creating the withSideEffect steps directly after g, the GraphTraversalSource, makes it difficult for me to write composable functions. In general, I've been chaining queries together by writing functions that take an existing GraphTraversal and return an extended GraphTraversal. Note that the commented out sideEffect traversal steps would solve my composability issue, but they do not work.

So: is there a function I can call on a GraphTraversal that lets me set constants for usage in math?

let query = this.g
      .withSideEffect('rdeg', 0.017453293)
      .withSideEffect('gcmiles', 3956)
      .withSideEffect('sourceLat', lat)
      .withSideEffect('sourceLng', lng)
      .withSideEffect('radius', radius)
      .V()
      // .sideEffect('rdeg', 0.017453293)
      // .sideEffect('gcmiles', 3956)
      // .sideEffect('sourceLat', lat)
      // .sideEffect('sourceLng', lng)
      // .sideEffect('radius', radius)
      .hasLabel('place')
      .has('latitude')
      .has('longitude')
      .as('dst')
      .where(
        __.select('dst')
          .by(__.project('lat', 'lon').by('latitude').by('longitude'))
          .as('dstGrp')
          .project('ladiff', 'lgdiff', 'lat1', 'lon1', 'lat2', 'lon2')
          .by(
            __.project('la1', 'la2')
              .by(__.select('dstGrp').select('lat'))
              .by(__.select('sourceLat'))
              .math('(la2 - la1) * rdeg'),
          )
          .by(
            __.project('lg1', 'lg2')
              .by(__.select('dstGrp').select('lon'))
              .by(__.select('sourceLng'))
              .math('(lg2 - lg1) * rdeg'),
          )
          .by(__.select('dstGrp').select('lat'))
          .by(__.select('dstGrp').select('lon'))
          .by(__.select('sourceLat'))
          .by(__.select('sourceLng'))
          .math('(sin(ladiff/2))^2 + cos(lat1*rdeg) * cos(lat2*rdeg) * (sin(lgdiff/2))^2')
          .math('gcmiles * (2 * asin(sqrt(_)))')
          .is(gremlin.process.P.lt(radius)),
      );

I would like to be able to write something that looks like this, using the function excerpted above:

let placesQuery = this.g
      .V(userId)
      .out('IS_FRIENDS_WITH')
      .union(__.out('IS_INTERESTED_IN'), __.out('BOOKMARKED'))
      .hasLabel('place')
      .not(__.or(__.in_('IS_INTERESTED_IN').hasId(userId), __.in_('BOOKMARKED').hasId(userId)));
    
placesQuery = this.withinHaversineDistanceWithBoundingBoxQuery(placesQuery);
1
  • I also tried replacing withSideEffect with sideEffect(__.constant(0.017453293).as('rdeg')) but the math step throws an error: "The variable rdeg for math() step must resolve to a Number - it is instead of type null with value null"}
    – ashissl
    Commented Jun 18 at 16:45

0

Browse other questions tagged or ask your own question.