Announcement Announcement Module
Collapse
No announcement yet.
Can't figure out Cypher queries even when I duplicate what is in the docs. Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Can't figure out Cypher queries even when I duplicate what is in the docs.

    I think we need more examples in the samples or docs on how to write Cypher Queries in our Spring Data Neo4J Repositories. The sections that talk about putting @Query on your methods is too sparse.

    Here is my query as it stands now

    Code:
    @Query("start user=node: " +
        	"match (user)-[:FRIEND]->(friend)-[:FRIEND]->(friendOfFriend) " +
        	"return friendOfFriend " +
        	"order by count(*) desc")
        public Page<User> findFriendsOfFriends(@Param("node") User user, Pageable pageable);
    And my current exception is

    Caused by: org.neo4j.cypher.SyntaxException: `=' expected but `)' found

    I have tried many different versions based on stuff in the docs from

    start movie=node:Movie(title='Matrix') match (movie)<-[:ACTS_IN]-(actor) return actor.name
    where I have each node in the match in parenthesis like what I have above

    To trying not having parentheses because I saw this in the docs
    // start person=node:__types__("className"="com...Person")
    // where person.age = {0} and person.married = {1}
    // return person

    And tried this which I found in the docs

    Code:
    interface MovieRepository extends GraphRepository<Movie> {
    	@Query("
    	start user=node({0}) 
    	match user-[:FRIEND]-friend-[r:RATED]->movie
    	return movie
    	order by avg(r.stars) desc, count(*) desc
    	limit 10
    	")
        Iterabe<Movie> recommendMovies(User me);
    }
    If I try

    Code:
    @Query("start user=node({0}) match (user)-[:FRIEND]->(friend)-[:FRIEND]->(friendOfFriend) return friendOfFriend order by count(*) desc")
        public Page<User> findFriendsOfFriends(User user, Pageable pageable);
    I get a exception trace of

    Code:
    java.util.NoSuchElementException
    	at scala.collection.TraversableLike$$anonfun$2.apply(TraversableLike.scala:372)
    	at scala.collection.TraversableLike$$anonfun$2.apply(TraversableLike.scala:372)
    	at scala.collection.TraversableLike$class.head(TraversableLike.scala:379)
    	at org.neo4j.cypher.pipes.Pipe.head(Pipe.scala:31)
    	at org.neo4j.cypher.pipes.SlicePipe.foreach(SlicePipe.scala:30)
    	at org.neo4j.cypher.pipes.ColumnFilterPipe.foreach(ColumnFilterPipe.scala:35)
    	at scala.collection.TraversableLike$class.map(TraversableLike.scala:194)
    	at org.neo4j.cypher.pipes.Pipe.map(Pipe.scala:31)
    	at org.neo4j.cypher.ExecutionResult$class.javaIterator(ExecutionResult.scala:49)
    	at org.neo4j.cypher.pipes.ColumnFilterPipe.javaIterator(ColumnFilterPipe.scala:25)
    	at org.neo4j.cypher.javacompat.ExecutionResult.iterator(ExecutionResult.java:51)
    	at org.springframework.data.neo4j.conversion.QueryResultBuilder$1.iterator(QueryResultBuilder.java:112)
    	at org.neo4j.helpers.collection.IteratorUtil.addToCollection(IteratorUtil.java:339)
    	at org.springframework.data.neo4j.repository.query.GraphRepositoryQuery.createPage(GraphRepositoryQuery.java:107)
    	at org.springframework.data.neo4j.repository.query.GraphRepositoryQuery.dispatchQuery(GraphRepositoryQuery.java:88)
    	at org.springframework.data.neo4j.repository.query.GraphRepositoryQuery.execute(GraphRepositoryQuery.java:70)
    	at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:301)
    	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
    	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    	at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
    	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
    	at $Proxy50.findFriendsOfFriends(Unknown Source)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:318)
    	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:196)
    	at $Proxy52.findFriendsOfFriends(Unknown Source)
    	at com.perfectworldprogramming.eventgate.user.UserDBTests.testFindFriendsOfFriends(UserDBTests.java:141)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    	at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
    	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
    	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
    	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
    	at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
    	at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
    	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:71)
    	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:202)
    	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:63)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
    So no luck

    Will the real slim shady please stand up?

    Thanks for you help

    Mark
    Last edited by bytor99999; Feb 2nd, 2012, 06:16 PM. Reason: add more

  • #2
    This query looks like it is working, and really isn't much different except without the [:FRIENDS] part to state the relationship name.

    @Query("start user=node({0}) match user-->friends-->friendsOfFriends return friendsOfFriends order by count(*) desc")

    I had to start with a small query just to get the "start" portion syntax correct with return, then added order by clause, then tried user-->friend which didn't work, then user-->friends which did work. Then just extended it out to two nodes away.

    Thanks

    Mark

    Comment


    • #3
      I spoke too soon. While that query above did not cause an exception, it still wasn't returning the correct data. So now I have

      Code:
      @Query("start user=node({0}) " +
                  "match user-[?:FRIENDS]-f-[?:FRIENDS]-fof " +
                  "return fof " +
                  "order by count(*) desc")
          public Page<User> findFriendsOfFriends(User user, Pageable pageable);
          
          @Query("start user=node({0}) " +
                 "match user-[?:FRIENDS]-f " +
                 "return f " +
                 "order by f.lastName asc")
          public Page<User> findFriends(User user, Pageable page);
      I had to put the specific relationship type, and that it could be there or not, because without the "?" for optional I got an exception.

      With these queries above, there aren't exceptions, but no results back either even though I have data in the db that should match and return some data. I have auser which is friends with cuser, and buser is also friends with cuser, so if I search for friends of friends for auser, I should get back buser, but I get nothing in the contents.

      Same with findFriends query. If I try to find cuser's friends I should get two Users back a and b user. But again I get nothing in the contents. empty.

      What am I doing wrong?

      Thanks

      Mark

      Comment


      • #4
        Mark,

        so you figured it out on your own, sorry for the late reply.

        In the first query you missed the index part : start user = node:Users(login={0}) ...
        general syntax is: node:<indexName>(<indexKey>=<indexValue>) ...

        for your query that don't return something - cypher matches subgraphs if it doesn't find any subgraphs it returns an empty result, which is then causing the issue, can you file a bug on JIRA for the java.util.NoSuchElementException.

        If you leave off relationship-types as you did with the FRIEND it takes any arbitrary outgoing relationship and uses that and returns the node at the end of it (which might not what you intended).

        If you have queries that should result in a single value (or null) you should either use optional relationships like me-[?:FRIEND]->friend which return null or have them result in a collection object (which might then be empty). This will be alleviated in the future so that empty results also result in a null value for a single result.

        In your last post you used FRIEND_S_ and in the others FRIEND, perhaps that's why it didn't find any results?

        Cheers

        Michael

        Comment


        • #5
          Thanks.

          "In your last post you used FRIEND_S_ and in the others FRIEND, perhaps that's why it didn't find any results?"

          That's what happens when you stop using your own constant that has the correct "FRIEND" String assigned to it. But I did remove the constant remove a variable from the equation as a possible reason why my query wasn't working.

          Thanks again.

          Mark

          Comment


          • #6
            I commented on the 196? I am still getting the exception with SDN 2.0.1.RELEASE. It is starting to create an issue in my app. The other one I could work around. This one affects a lot of areas in my code for the web app. I could put all these try catches around everything but, I try to avoid any try-catch anywhere in my code. Or I could just create an aspect class to do that part. That would be cleaner here.

            Mark

            Comment


            • #7
              Could you please show mvn dependency:tree to make sure that you have the latest neo4j/cypher versions?

              Also you may share your app privately with me, so that I can have a look at the issue.

              Michael

              Comment


              • #8
                Which Neo4j/Cypher versions are you expecting. The Jira only talked about the SDN version needed.

                I am still on Neo4j 1.5

                Don't need to run tree on it, I got IntelliJ.

                Mark

                Comment


                • #9
                  Upgraded to Neo4j 1.6 and it now works, no Exception. Thanks!

                  Although I did have to delete my database because it was based on 1.5. It gave me a message about putting something about auto-update=true somewhere, but it didn't state exactly where. I am using the Embedded Neo4J with SDN, so the only config files I have are Spring config files. Spring Roo did create a neo4j.properties file with the location property in it, and I have added allow_store_upgrade=true also in the .properties file, but it didn't upgrade my database, I had to delete the database.

                  Where can I put allow_store_upgrade=true so that in the future when there is actually real data in the database that I don't have to delete it and lose all that data?

                  Thanks

                  Mark

                  Comment


                  • #10
                    You just pass it in to your embedded graphdb config as stated in the docs

                    http://static.springsource.org/sprin.../html/#d0e3354

                    Code:
                    <context:annotation-config/>
                    
                    <bean id="graphDatabaseService" class="org.neo4j.kernel.EmbeddedGraphDatabase"
                            destroy-method="shutdown">
                        <constructor-arg index="0" value="target/config-test"/>
                        <constructor-arg index="1">
                            <map>
                                <entry key="allow_store_upgrade" value="true"/>
                            </map>
                        </constructor-arg>
                    </bean>
                    
                    <neo4j:config graphDatabaseService="graphDatabaseService"/>

                    Comment


                    • #11
                      My config doesn't look like that at all. What I took from the docs was

                      Code:
                          <neo4j:config storeDirectory="${neo4j.location}"/>
                          <neo4j:repositories base-package="com.perfectworldprogramming.eventgate"/>
                          <tx:annotation-driven mode="proxy"/>
                      I don't think we should need to write more xml just to add one property. What about the <neo4j:config have an attribute for it instead.

                      Sorry, but this is partly what I am trying to show, is that unfortunately, the docs make too many assumptions.

                      I mean this in a nice way, but there can be a culture difference. You know us Americans, we want everything given to us on a silver platter with specific documentation laid out telling us everything.

                      If someone is a newbie like me that just wants to jump right into SDN, I will only read the SDN docs including my introduction to Neo4J and will expect that to be fully covered. Mainly because we know that SDN makes things so much simpler, that we don't have to spend even more time reading other docs to figure it all out. I modeled my app around the Cineasts app in the docs expecting it to just work, but found that there were many hidden gems not shown in the docs that were just as important to know and understand to make it work.

                      I hope you understand, I am not trying to be mean, or negative, or anything bad. I just want to make it better than how great it already is.

                      Mark

                      Comment


                      • #12
                        Your config covers the simplest case possible, the 80 percent case.

                        In the 20 percent case you have to do more (that involves store upgrades, auto-upgrading is also not an option b/c this is something that should be controlled). So upgrading it explicitly in a separate step/program would be sensible.

                        Probably it is cultural, but it is also about complexity and effort. So you don't want to have everything documented upfront b/c it would pollute the basic use-cases with too much detail. Same goes for the configuration, if we had every neo4-configuration option in the namespace it would have 30 or so attributes which confuses more than it helps.

                        So far people were ok with this approach. Also completely hiding that there is a full database system running under the hood makes not much sense as this would blur people's sense (full transparency is not the goal and also not useful).

                        Don't get me wrong I'm really thankful for the feedback, please continue to line out shortcomings in docs and configuration. Can you raise an issue for this? I think a sensible solution would be to provide a separate command line app within that just updates the store (on demand). And document this / put it in the exception message.

                        Comment


                        • #13
                          Yeah, if it was really bad, I wouldn't be sticking around. I am very fast to jump away from using projects that aren't great.

                          That is why I jumped away from ROO. I tried to keep as much code that ROO generated, but as each day goes by there is more and more I have ripped out. I have already removed using it, and pushed in all its code, but I have been deleting a lot of the pushed in code. The only code from ROO I still have left are the getters and setters in my domain objects and the pom file.

                          So, I am a still confused. If I use the configuration you posted, that will automatically upgrade my database whenever I upgrade Neo4j.

                          What is the part about creating a standalone application and running it from the command line part? I hope I don't have to do anything like that. Even if I change the structure of some Nodes and add new types of Nodes and Relationships, I don't think there is a schema or upgrade you have to do to your database, right?

                          Thanks

                          Mark

                          Comment


                          • #14
                            I meant: Upgrading from one store version to another (irreversible) is an ops-task, that should not be something that is done on the fly by the app, but consciously by a operator. That's why a simple tool (like the neo4j-shell) would be more sensible for this.

                            It is not about schema upgrades but store versions.

                            Comment


                            • #15
                              Thanks, I made the config change and finally found it in the docs, near the end sections.

                              Which issue to create? To create a command line script? Or, adding an attribute to

                              <neo4j:config storeDirectory="${neo4j.location}"/>

                              like update="true"

                              <neo4j:config storeDirectory="${neo4j.location}" update="true"/>



                              Mark
                              Last edited by bytor99999; Feb 13th, 2012, 06:29 PM. Reason: add

                              Comment

                              Working...
                              X