| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| package org.apache.s2graph.core.index |
| |
| import java.util |
| |
| import com.typesafe.config.Config |
| import org.apache.s2graph.core._ |
| import org.apache.s2graph.core.mysqls._ |
| import org.apache.s2graph.core.types.VertexId |
| import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer |
| import org.apache.tinkerpop.gremlin.process.traversal.util.{AndP, OrP} |
| import org.apache.tinkerpop.gremlin.process.traversal.{Compare, Contains} |
| import org.apache.tinkerpop.gremlin.structure.T |
| |
| import scala.concurrent.{ExecutionContext, Future} |
| import scala.util.Try |
| |
| object IndexProvider { |
| import GlobalIndex._ |
| //TODO: Fix Me |
| val hitsPerPage = 100000 |
| val IdField = "id" |
| |
| def apply(config: Config)(implicit ec: ExecutionContext): IndexProvider = { |
| |
| val indexProviderType = Try { config.getString("index.provider") }.getOrElse("lucene") |
| |
| indexProviderType match { |
| case "lucene" => new LuceneIndexProvider(config) |
| case "es" => new ESIndexProvider(config) |
| } |
| } |
| |
| def buildQuerySingleString(container: HasContainer): String = { |
| import scala.collection.JavaConversions._ |
| |
| val key = if (container.getKey == T.label.getAccessor) labelField else container.getKey |
| val value = container.getValue |
| |
| container.getPredicate match { |
| case and: AndP[_] => |
| val buffer = scala.collection.mutable.ArrayBuffer.empty[String] |
| and.getPredicates.foreach { p => |
| buffer.append(buildQuerySingleString(new HasContainer(container.getKey, p))) |
| } |
| buffer.mkString("(", " AND ", ")") |
| case or: OrP[_] => |
| val buffer = scala.collection.mutable.ArrayBuffer.empty[String] |
| or.getPredicates.foreach { p => |
| buffer.append(buildQuerySingleString(new HasContainer(container.getKey, p))) |
| } |
| buffer.mkString("(", " OR ", ")") |
| case _ => |
| val biPredicate = container.getBiPredicate |
| biPredicate match { |
| |
| case Contains.within => |
| key + ":(" + value.asInstanceOf[util.Collection[_]].toSeq.mkString(" OR ") + ")" |
| case Contains.without => |
| "NOT " + key + ":(" + value.asInstanceOf[util.Collection[_]].toSeq.mkString(" AND ") + ")" |
| case Compare.eq => s"${key}:${value}" |
| case Compare.gt => s"(${key}:[${value} TO *] AND NOT ${key}:${value})" |
| case Compare.gte => s"${key}:[${value} TO *]" |
| case Compare.lt => s"${key}:[* TO ${value}]" |
| case Compare.lte => s"(${key}:[* TO ${value}] OR ${key}:${value})" |
| case Compare.neq => s"NOT ${key}:${value}" |
| case _ => throw new IllegalArgumentException("not supported yet.") |
| } |
| } |
| } |
| |
| def buildQueryString(hasContainers: java.util.List[HasContainer]): String = { |
| import scala.collection.JavaConversions._ |
| val builder = scala.collection.mutable.ArrayBuffer.empty[String] |
| |
| hasContainers.foreach { container => |
| container.getPredicate match { |
| case and: AndP[_] => |
| val buffer = scala.collection.mutable.ArrayBuffer.empty[String] |
| and.getPredicates.foreach { p => |
| buffer.append(buildQuerySingleString(new HasContainer(container.getKey, p))) |
| } |
| builder.append(buffer.mkString("(", " AND ", ")")) |
| case or: OrP[_] => |
| val buffer = scala.collection.mutable.ArrayBuffer.empty[String] |
| or.getPredicates.foreach { p => |
| buffer.append(buildQuerySingleString(new HasContainer(container.getKey, p))) |
| } |
| builder.append(buffer.mkString("(", " OR ", ")")) |
| case _ => |
| builder.append(buildQuerySingleString(container)) |
| } |
| } |
| |
| builder.mkString(" AND ") |
| } |
| } |
| |
| trait IndexProvider { |
| //TODO: Seq nee do be changed into stream |
| def fetchEdgeIds(hasContainers: java.util.List[HasContainer]): java.util.List[EdgeId] |
| def fetchEdgeIdsAsync(hasContainers: java.util.List[HasContainer]): Future[java.util.List[EdgeId]] |
| |
| def fetchVertexIds(hasContainers: java.util.List[HasContainer]): java.util.List[VertexId] |
| def fetchVertexIdsAsync(hasContainers: java.util.List[HasContainer]): Future[java.util.List[VertexId]] |
| def fetchVertexIdsAsyncRaw(vertexQueryParam: VertexQueryParam): Future[java.util.List[VertexId]] = Future.successful(util.Arrays.asList()) |
| |
| def mutateVertices(vertices: Seq[S2VertexLike], forceToIndex: Boolean = false): Seq[Boolean] |
| def mutateVerticesAsync(vertices: Seq[S2VertexLike], forceToIndex: Boolean = false): Future[Seq[Boolean]] |
| |
| def mutateEdges(edges: Seq[S2EdgeLike], forceToIndex: Boolean = false): Seq[Boolean] |
| def mutateEdgesAsync(edges: Seq[S2EdgeLike], forceToIndex: Boolean = false): Future[Seq[Boolean]] |
| |
| def shutdown(): Unit |
| } |