gremlin sideEffect 的替代方案,因为 Neptune 不支持它?

Alternative for gremlin sideEffect since Neptune doesn't support it?

在 AWS Neptune 中,我正在尝试通过计算余弦相似度来创建用户顶点之间的相似度边,如 Daniel Kuppitz here -- https://gist.github.com/dkuppitz/79e0b009f0c9ae87db5a#file-cosim-groovy-L368 所述——gremlin 的 sideEffect 提供了一个有用的闭包,它允许进行一些数学计算以获得相似度分数并将此值写入每个 'similarity' 边。唉,Neptune 不支持 sideEffect。我正在寻找一种在不使用 sideEffect 的情况下在单个 gremlin 查询中 运行 下面示例中的注释部分的方法。感谢您的帮助!

g.V().match(
__.as("u1").outE("rated").as("r1"),
__.as("r1").inV().as("m"),
__.as("m").inE("rated").as("r2"),
__.as("r2").outV().as("u2")
).where("u1", neq("u2")).
group().by(select("u1","u2")).
by(select("r1","r2").by("rating")).
unfold().
as("kv").
select(keys).
addE("similarity").from("u1").to("u2").as("e").
// sideEffect {
//   def r = it.get("kv").getValue()
//   def xyDotProduct = r.collect {it.r1*it.r2}.sum()
//   def xLength = Math.sqrt(r.collect {it.r1*it.r1}.sum())
//   def yLength = Math.sqrt(r.collect {it.r2*it.r2}.sum())
//   def similarity = xyDotProduct / (xLength * yLength)
//   it.get().property("similarity", similarity)
// }.iterate()

Amazon Neptune 支持 sideEffect 步骤,但不支持对任何步骤使用 Groovy 闭包。我相信使用 mathproject 步骤的组合可能会实现示例中显示的相同效果。这是一个 link 与 Haversine Greater Circle 距离有点相似(在复杂性方面)的计算。也许您可以使用类似于 this one from Practical Gremlin.

的方法
start = 'SFO'
stop = 'NRT'

g.withSideEffect("rdeg", 0.017453293).
  withSideEffect("gcmiles",3956).
  V().has('code',start).as('src').
  V().has('code',stop).as('dst').
  select('src','dst').
    by(project('lat','lon').
         by('lat').
         by('lon')).
  as('grp').
  project('ladiff','lgdiff','lat1','lon1','lat2','lon2').
    by(project('la1','la2').
         by(select('grp').select('src').select('lat')).
         by(select('grp').select('dst').select('lat')).
       math('(la2 - la1) * rdeg')).
    by(project('lg1','lg2').
         by(select('grp').select('src').select('lon')).
         by(select('grp').select('dst').select('lon')).
       math('(lg2 - lg1) * rdeg')).
    by(select('grp').select('src').select('lat')).
    by(select('grp').select('src').select('lon')).
    by(select('grp').select('dst').select('lat')).
    by(select('grp').select('dst').select('lon')).
  math('(sin(ladiff/2))^2 + cos(lat1*rdeg) * cos(lat2*rdeg) * (sin(lgdiff/2))^2').
  math('gcmiles * (2 * asin(sqrt(_)))')

这种方法不是在闭包内使用变量,而是使用 project 有效地创建仍然可以传递给 math 步骤的相同变量。