performance tunning for IN clause on where parser
Project: http://git-wip-us.apache.org/repos/asf/incubator-s2graph/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-s2graph/commit/e9748524 Tree: http://git-wip-us.apache.org/repos/asf/incubator-s2graph/tree/e9748524 Diff: http://git-wip-us.apache.org/repos/asf/incubator-s2graph/diff/e9748524 Branch: refs/heads/feature/test_daewon Commit: e974852433ebedb2dcd9e0e6a6da1317f359ae6d Parents: a6acec7 Author: SteamShon <[email protected]> Authored: Tue Dec 22 17:28:47 2015 +0900 Committer: SteamShon <[email protected]> Committed: Tue Dec 22 17:28:47 2015 +0900 ---------------------------------------------------------------------- .../s2graph/core/parsers/WhereParser.scala | 30 ++++++++++++++++---- .../kakao/s2graph/core/rest/RequestParser.scala | 8 +++--- 2 files changed, 28 insertions(+), 10 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/e9748524/s2core/src/main/scala/com/kakao/s2graph/core/parsers/WhereParser.scala ---------------------------------------------------------------------- diff --git a/s2core/src/main/scala/com/kakao/s2graph/core/parsers/WhereParser.scala b/s2core/src/main/scala/com/kakao/s2graph/core/parsers/WhereParser.scala index 15996ea..2a62b3b 100644 --- a/s2core/src/main/scala/com/kakao/s2graph/core/parsers/WhereParser.scala +++ b/s2core/src/main/scala/com/kakao/s2graph/core/parsers/WhereParser.scala @@ -98,15 +98,28 @@ case class Eq(propKey: String, value: String) extends Clause { override def filter(edge: Edge): Boolean = binaryOp(_ == _)(propKey, value)(edge) } +case class InWithoutParent(label: Label, propKey: String, values: Set[String]) extends Clause { + val innerValLikeLs = values.map { value => + val labelMeta = label.metaPropsInvMap.getOrElse(propKey, throw WhereParserException(s"Where clause contains not existing property name: $propKey")) + val dataType = propKey match { + case "_to" | "to" => label.tgtColumn.columnType + case "_from" | "from" => label.srcColumn.columnType + case _ => labelMeta.dataType + } + toInnerVal(value, dataType, label.schemaVersion) + } + override def filter(edge: Edge): Boolean = { + val propVal = propToInnerVal(edge, propKey) + innerValLikeLs.contains(propVal) + } +} + case class IN(propKey: String, values: Set[String]) extends Clause { override def filter(edge: Edge): Boolean = { val propVal = propToInnerVal(edge, propKey) values.exists { value => valueToCompare(edge, propKey, value) == propVal } -// val valuesToCompare = values.map { value => valueToCompare(edge, propKey, value) } -// -// valuesToCompare.contains(propVal) } } @@ -136,7 +149,7 @@ object WhereParser { val success = Where() } -case class WhereParser(labelMap: Map[String, Label]) extends JavaTokenParsers with JSONParser { +case class WhereParser(label: Label) extends JavaTokenParsers with JSONParser { val anyStr = "[^\\s(),]+".r @@ -174,8 +187,13 @@ case class WhereParser(labelMap: Map[String, Label]) extends JavaTokenParsers wi case f ~ minV ~ maxV => Between(f, minV, maxV) } | identWithDot ~ (notIn | in) ~ ("(" ~> repsep(anyStr, ",") <~ ")") ^^ { case f ~ op ~ values => - if (op.toLowerCase == "in") IN(f, values.toSet) - else Not(IN(f, values.toSet)) + val inClause = + if (f.startsWith("_parent")) IN(f, values.toSet) + else InWithoutParent(label, f, values.toSet) + if (op.toLowerCase == "in") inClause + else Not(inClause) + + case _ => throw WhereParserException(s"Failed to parse where clause. ") } } http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/e9748524/s2core/src/main/scala/com/kakao/s2graph/core/rest/RequestParser.scala ---------------------------------------------------------------------- diff --git a/s2core/src/main/scala/com/kakao/s2graph/core/rest/RequestParser.scala b/s2core/src/main/scala/com/kakao/s2graph/core/rest/RequestParser.scala index 96d8f60..f9a6d01 100644 --- a/s2core/src/main/scala/com/kakao/s2graph/core/rest/RequestParser.scala +++ b/s2core/src/main/scala/com/kakao/s2graph/core/rest/RequestParser.scala @@ -92,11 +92,11 @@ class RequestParser(config: Config) extends JSONParser { ret.map(_.toMap).getOrElse(Map.empty[Byte, InnerValLike]) } - def extractWhere(labelMap: Map[String, Label], whereClauseOpt: Option[String]) = { + def extractWhere(label: Label, whereClauseOpt: Option[String]) = { whereClauseOpt match { case None => Success(WhereParser.success) case Some(where) => - WhereParser(labelMap).parse(where) match { + WhereParser(label).parse(where) match { case s@Success(_) => s case Failure(ex) => throw BadQueryException(ex.getMessage, ex) } @@ -251,7 +251,7 @@ class RequestParser(config: Config) extends JSONParser { } } - private def parseQueryParam(labelMap: Map[String, Label], labelGroup: JsValue): Option[QueryParam] = { + private def parseQueryParam(labelGroup: JsValue): Option[QueryParam] = { for { labelName <- parse[Option[String]](labelGroup, "label") } yield { @@ -280,7 +280,7 @@ class RequestParser(config: Config) extends JSONParser { case Some(indexName) => label.indexNameMap.get(indexName).map(_.seq).getOrElse(throw new RuntimeException("cannot find index")) } val whereClauseOpt = (labelGroup \ "where").asOpt[String] - val where = extractWhere(labelMap, whereClauseOpt) + val where = extractWhere(label, whereClauseOpt) val includeDegree = (labelGroup \ "includeDegree").asOpt[Boolean].getOrElse(true) val rpcTimeout = (labelGroup \ "rpcTimeout").asOpt[Int].getOrElse(DefaultRpcTimeout) val maxAttempt = (labelGroup \ "maxAttempt").asOpt[Int].getOrElse(DefaultMaxAttempt)
