orientechnologies / orientdb-gremlin

TinkerPop3 Graph Structure Implementation for OrientDB
Apache License 2.0
91 stars 32 forks source link

Problem with traversing on indexed properties #71

Closed wildroco closed 8 years ago

wildroco commented 8 years ago

environment: OrientDB 2.1.15 (localhost) gremlin-scala 3.1.2-incubating.0 orientdb-gremlin 3.1.1-incubating.1

When I traverse on indexed properties, got this exception: java.lang.ClassCastException: com.orientechnologies.orient.core.record.impl.ODocument cannot be cast to com.orientechnologies.orient.core.id.ORecordId (full stack trace is below)

This is my code raising exception.

graphDB.withGraph { graph => graph.V.hasLabel("MyLabel") .has("indexedProperty", "some-value") .headOption()

}

everything is fine if I try same query after removing index from "indexedProperty",

What I have to do? I really want to use scala - gremlin - orientDB stack.

full stack trace of exception

java.lang.ClassCastException: com.orientechnologies.orient.core.record.impl.ODocument cannot be cast to com.orientechnologies.orient.core.id.ORecordId at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) at java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1540) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499) at org.apache.tinkerpop.gremlin.orientdb.traversal.step.sideEffect.OrientGraphStep.vertices(OrientGraphStep.java:60) at org.apache.tinkerpop.gremlin.orientdb.traversal.step.sideEffect.OrientGraphStep.lambda$new$0(OrientGraphStep.java:40) at org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep.processNextStart(GraphStep.java:123) at org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep.hasNext(AbstractStep.java:140) at org.apache.tinkerpop.gremlin.process.traversal.step.util.ExpandableStepIterator.next(ExpandableStepIterator.java:54) at org.apache.tinkerpop.gremlin.process.traversal.step.map.MapStep.processNextStart(MapStep.java:36) at org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep.hasNext(AbstractStep.java:140) at org.apache.tinkerpop.gremlin.process.traversal.step.util.ExpandableStepIterator.next(ExpandableStepIterator.java:54) at org.apache.tinkerpop.gremlin.process.traversal.step.map.MapStep.processNextStart(MapStep.java:36) at org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep.hasNext(AbstractStep.java:140) at org.apache.tinkerpop.gremlin.process.traversal.step.util.ExpandableStepIterator.next(ExpandableStepIterator.java:54) at org.apache.tinkerpop.gremlin.process.traversal.step.map.MapStep.processNextStart(MapStep.java:36) at org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep.next(AbstractStep.java:126) at org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep.next(AbstractStep.java:37) at org.apache.tinkerpop.gremlin.process.traversal.Traversal.fill(Traversal.java:147) at org.apache.tinkerpop.gremlin.process.traversal.Traversal.toList(Traversal.java:104) at gremlin.scala.GremlinScala.toList(GremlinScala.scala:28) at gremlin.scala.GremlinScala.headOption(GremlinScala.scala:37) at models.dao.PasswordInfoDao$$anonfun$update$1$$anonfun$apply$4.apply(PasswordInfoDao.scala:43) at models.dao.PasswordInfoDao$$anonfun$update$1$$anonfun$apply$4.apply(PasswordInfoDao.scala:36) at services.GraphDB.withGraph(GraphDB.scala:57) at models.dao.PasswordInfoDao$$anonfun$update$1.apply(PasswordInfoDao.scala:36) at models.dao.PasswordInfoDao$$anonfun$update$1.apply(PasswordInfoDao.scala:33) at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24) at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24) at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:39) at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:405) at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)

mpollmeier commented 8 years ago

Can you put together a mini-repo with a test that demonstrates this, which I can use to test/verify? You could just take the orient project inside https://github.com/mpollmeier/gremlin-scala-examples

The fix is probably quite simple, but I don't have the time right now to setup everything myself.

johnrevill commented 8 years ago

I was getting the same ClassCastExceptioon with the same message, albeit coming from Java. Thought I'd post out what I found in case it helps..

For me, it turned out to be down to the way in which the index was created in code. I was calling the org.apache.tinkerpop.gremlin.orientdb.OrientGraph.createVertexIndex(String, String, Configuration) method but with the wrong details in the Configuration object. It didn't complain at the point of creating the index, but did cause the same stacktrace you're seeing. The passed Configuration needed a "type" property and "keytype" property (see the code at https://github.com/mpollmeier/orientdb-gremlin/blob/3.1.1-incubating.1/driver/src/main/java/org/apache/tinkerpop/gremlin/orientdb/OrientGraph.java#L606).

Here's a simple unit test that shows a working traversal with a unique string index:

import static org.junit.Assert.assertTrue;

import java.util.logging.Level;

import org.apache.commons.configuration.BaseConfiguration;
import org.apache.commons.configuration.Configuration;
import org.apache.tinkerpop.gremlin.orientdb.OrientGraph;
import org.apache.tinkerpop.gremlin.orientdb.OrientGraphFactory;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.orientechnologies.orient.client.remote.OServerAdmin;
import com.orientechnologies.orient.core.metadata.schema.OClass;
import com.orientechnologies.orient.core.metadata.schema.OType;
import com.orientechnologies.orient.server.OServer;
import com.orientechnologies.orient.server.OServerMain;

public class IndexTest {
  private OServer testserver;
  private OrientGraphFactory factory;

  @Before
  public void before() throws Exception {
    final String dbJULoggingLevel = Level.FINE.toString();
    final String dbRootPwd = "test";
    final String dbLocalPort = "55123";

    this.testserver = OServerMain.create();

    testserver.startup(
        "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
            + "<orient-server>"
            + "  <network>"
            + "    <protocols>"
            + "      <protocol name=\"binary\" implementation=\"com.orientechnologies.orient.server.network.protocol.binary.ONetworkProtocolBinary\"/>"
            + "      <protocol name=\"http\" implementation=\"com.orientechnologies.orient.server.network.protocol.http.ONetworkProtocolHttpDb\"/>"
            + "    </protocols>"
            + "    <listeners>"
            + "      <listener ip-address=\"0.0.0.0\" port-range=\""+dbLocalPort+"\" protocol=\"binary\"/>"
            + "    </listeners>"
            + "  </network>"
            + "  <users><user name=\"root\" password=\""+dbRootPwd+"\" resources=\"*\"/></users>"
            + "<properties>"
            + "  <entry name=\"server.cache.staticResources\" value=\"false\"/>"
            + "  <entry name=\"log.console.level\" value=\""+dbJULoggingLevel+"\"/>"
            + "  <entry name=\"log.file.level\" value=\"off\"/>"
            //The following is required to eliminate an error or warning "Error on resolving property: ORIENTDB_HOME"
            + "  <entry name=\"plugin.dynamic\" value=\"false\"/>"
            + "</properties>" 
            + "</orient-server>");

    testserver.activate();

    final String connUrl = String.format("remote:localhost:%s/testgraph", dbLocalPort);

    OServerAdmin testServerAdmin = new OServerAdmin(connUrl).connect("root", dbRootPwd);
    testServerAdmin.createDatabase("graph", "memory");

    this.factory = new OrientGraphFactory(connUrl, "root", dbRootPwd);
  }

  @After
  public void after() {
    testserver.shutdown();
  }

  @Test
  public void traverseWithIndex() {
    final String vertexClassLabel = "user";
    final String indexedPropName = "user_id";

    {
      // Set up a class "user" and create an indexed property "user_id" for it 
      final OrientGraph dbNoTx = this.factory.getNoTx();

      final Configuration indexConf = new BaseConfiguration();
      indexConf.setProperty("type", OClass.INDEX_TYPE.UNIQUE.name());
      indexConf.setProperty("keytype", OType.STRING);

      dbNoTx.createVertexIndex(indexedPropName, vertexClassLabel, indexConf);
    }

    final OrientGraph dbWithTx = this.factory.getTx();

    dbWithTx.addVertex(T.label, vertexClassLabel, indexedPropName, "1234");
    dbWithTx.tx().commit();

    assertTrue(dbWithTx.traversal().V().hasLabel(vertexClassLabel).has(indexedPropName, "1234").hasNext());
  }
}

If you ran that unit test with the "type" and "keytype" Configuration properties commented out, you'd see the ClassCastExceptioon.

In case it's helpful, here's the maven build file showing the versions involved in that unit test:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.foo</groupId>
    <artifactId>TP3Test</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>

        <dependency>
            <groupId>com.michaelpollmeier</groupId>
            <artifactId>orientdb-gremlin</artifactId>
            <version>3.1.1-incubating.1</version>
        </dependency>

        <dependency>
            <groupId>com.orientechnologies</groupId>
            <artifactId>orientdb-server</artifactId>
            <version>2.1.12</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

    </dependencies>
</project>
wildroco commented 8 years ago

@mpollmeier @johnrevill thx!

I had tried to create index with OrientGraph in wrong packge: com.tinkerpop.blueprints.impls.orient which (may) from original OrientDB driver.

After I correct the package for OrientGraph to org.apache.tinkerpop.gremlin.orientdb.OrientGraph and modify some codes as johnrevill sugessted, my index works perfectly :)