首页 > 解决方案 > 更新顶点时不支持 Apache Gremlin 将属性结果更新为属性添加

问题描述

这是我遇到的错误。

play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[IllegalStateException: Property addition is not supported]]
    at play.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:251)
    at play.api.http.DefaultHttpErrorHandler.onServerError(HttpErrorHandler.scala:178)
    at play.core.server.AkkaHttpServer$$anonfun$1.applyOrElse(AkkaHttpServer.scala:363)
    at play.core.server.AkkaHttpServer$$anonfun$1.applyOrElse(AkkaHttpServer.scala:361)
    at scala.concurrent.Future.$anonfun$recoverWith$1(Future.scala:413)
    at scala.concurrent.impl.Promise.$anonfun$transformWith$1(Promise.scala:37)
    at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:60)
    at akka.dispatch.BatchingExecutor$AbstractBatch.processBatch(BatchingExecutor.scala:55)
    at akka.dispatch.BatchingExecutor$BlockableBatch.$anonfun$run$1(BatchingExecutor.scala:91)
    at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12)
Caused by: java.lang.IllegalStateException: Property addition is not supported
    at org.apache.tinkerpop.gremlin.structure.Element$Exceptions.propertyAdditionNotSupported(Element.java:133)
    at org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex.property(DetachedVertex.java:91)
    at org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex.property(DetachedVertex.java:50)
    at gremlin.scala.ScalaElement.$anonfun$updateWith$2(ScalaElement.scala:76)
    at scala.collection.immutable.HashMap$HashMap1.foreach(HashMap.scala:231)
    at scala.collection.immutable.HashMap$HashTrieMap.foreach(HashMap.scala:462)
    at gremlin.scala.ScalaElement.updateWith(ScalaElement.scala:76)
    at gremlin.scala.ScalaElement.updateWith$(ScalaElement.scala:70)
    at gremlin.scala.ScalaVertex.updateWith(ScalaVertex.scala:8)
    at gremlin.scala.ScalaElement.updateAs(ScalaElement.scala:82)

这是我的模型以及我定义它的方式。

import java.util. UUID
import gremlin.scala.{Element, Marshallable, Vertex, id, label, underlying}


@label("trip")
case class TripModel(tripId: Option[String] = None,
                     name: String,
                     createdDate: java.time.Instant = java.time.Instant.now(),
                     startDate: java.time.Instant,
                     duration: Int,
                     totalAdults: Int,
                     totalChildrens: Int,
                     @underlying vertex: Option[Vertex] = None
                    )

object TripModel {

  implicit val marshaller = new Marshallable[TripModel] {
    def toCC(element: Element): TripModel = {
      val tripId = Some(element.value[UUID]("tripId").toString)
      val tripName = element.value[String]("name")
      val duration =  element.value[Int]("duration")
      val totalAdults = element.value[Short]("totalAdults")
      val totalChildren =element.value[Short]("totalChildrens")
      val date = element.value[java.time.Instant]("createdDate")
      val startDate = element.value[java.time.Instant]("startDate")

      models.TripModel(tripId = tripId, name = tripName,
        startDate  = startDate, duration = duration,
        totalAdults = totalAdults, totalChildrens = totalChildren, createdDate = date)
    }

    override def fromCC(cc: TripModel): FromCC = {
      val values = Map("name" -> cc.name,
        "createdDate" -> cc.createdDate,
        "startDate" -> cc.startDate,
        "duration"-> cc.duration,
        "totalAdults" -> cc.totalAdults,
        "totalChildrens" -> cc.totalChildrens,
        "tripId" -> UUID.fromString(cc.tripId.get).toString)
      FromCC(None, "trip", values)
    }
  }
}

我更新顶点的方式如下

def updateTripDetails(id:String, tripUpdate: UpdateTripRequest) = {
    implicit val g = db.g

    val item = db.g.V().has(KeyValue(tripId, id)).head
    item.updateAs[TripModel](cc => cc.copy(name = tripUpdate.tripName.getOrElse(cc.name)))
  }

我想做的是更新某个顶点属性,但是我总是收到上述错误。有什么解决方法吗?

我正在连接到 gremlin 服务器。这就是我建立连接的方式。

class GrDbConnection @Inject()  (config: Configuration) {

  private val dseCluster = DseCluster.builder()
    .addContactPoints(config.get[String]("dse.cluster.address"))
    .withPort(config.get[Int]("dse.cluster.port"))
    .build()

  private val graphName = "graphName"
  private val graphOptions = new GraphOptions().setGraphName(graphName)
  private val session = dseCluster.connect()

  session.executeGraph(new SimpleGraphStatement("schema.config().option('graph.schema_mode').set('development')").setGraphName(graphName))
  session.executeGraph(new SimpleGraphStatement("schema.config().option('graph.allow_scan').set('true')").setGraphName(graphName))
  // Create a ScalaGraph from a remote Traversal Source using withRemote
  // See: http://tinkerpop.apache.org/docs/current/reference/#connecting-via-remotegraph for more details
  private val connection = DseRemoteConnection.builder(session).withGraphOptions(graphOptions).build()
  val g:ScalaGraph = EmptyGraph.instance().asScala
    .configure(_.withRemote(connection))
}

标签: scalaplayframeworkgremlintinkerpop3

解决方案


你没有展示你是如何创建g的,但我假设你正在连接到一个远程图(例如,该图托管在 Gremlin 服务器中)而不是一个嵌入式的,所以在这种情况下这一行:

val item = db.g.V().has(KeyValue(tripId, id)).head

返回一个DetachedVertex。它不知道它所连接的图形,因此您可以将其视为只读的。您不直接更新其属性,而是使用 Gremlin 进行更新。我不知道 playframework 是如何处理底层更新的,但我敢打赌它不会期望“分离”的元素,而是假定一个本地嵌入的图实例,因此元素知道它们的主机图。

也就是说,更新顶点属性的正确方法是简单地使用 Gremlin 而不是直接对Vertex对象本身进行操作,因此您更喜欢像这样更新:

g.V(item).property('name', 'some name')

推荐阅读