Announcement Announcement Module
Collapse
No announcement yet.
Getting Neo4j cypher queries to work in java GraphRepository Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Getting Neo4j cypher queries to work in java GraphRepository

    I'm using a Neo4j database with various node classes and would like to search through the parameter strings of one particular node class. For example, if I have three nodes in class.MyNode, one with String name = "foo", another with name = "bar" and a third with name = "car", if I search for "ar", I would like to return a list containing nodes "bar" and "car".

    The following cypher query works perfectly well in Neo4j's data browser :

    Code:
    START n=node:__types__(className='com.myapp.MyNode')
    WHERE n.name=~ /(?i).*xyz.*/
    RETURN n
    However, when I add it to my repository, it returns all the nodes of class.MyNode and not the subset I need. Here is the code I've been using for the repository:

    Code:
    public interface MyNodeRepository extends GraphRepository<MyNode>,
    	RelationshipOperationsRepository<MyNode>,
    	NamedIndexRepository<MyNode>{
    	
    	@Query(	"START n=node:__types__(className='com.myapp.MyNode')"+ 
    			"WHERE n.name=~ /(?i).*{0}.*/"+
    			"RETURN n")
            Set<MyNode> getNodes(String search);	
    }
    And here is the node:

    Code:
    @NodeEntity
    public class MyNode {
    	@Indexed(indexType=IndexType.FULLTEXT, indexName="name") 
    	@Fetch private String name;
    
            etc
    }

    I'm passing parameters just like the bible suggests and I've been pulling my hair out trying to figure out why this doesn't work.

    Any thoughts on how to fix this would be much appreciated!!!

  • #2
    Michael,

    I'd suggest taking advantage of SDN's auto-repo-foo: http://static.springsource.org/sprin.../html/#d5e1308

    Code:
    @NodeEntity
    class MyNode {
        @GraphId
        private Long id;
    
        @Indexed(indexType = IndexType.FULLTEXT, indexName = "name")
        private String name;
    
        MyNode() {
        }
    
        public MyNode(String name) {
            this.name = name;
        }
    }
    
    interface MyNodeRepository extends GraphRepository<MyNode> {
        Page<MyNode> findByNameLike(String name, Pageable page);
    }
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration
    public class FullTextSearchTests {
        @Autowired
        private MyNodeRepository myNodeRepository;
    
        @Configuration
        @EnableNeo4jRepositories
        static class Config extends Neo4jConfiguration {
            @Bean
            public GraphDatabaseService graphDatabaseService() {
                return new ImpermanentGraphDatabase();
            }
        }
    
        @Test
        public void shouldFindBySubstring() throws Exception {
            myNodeRepository.save(new MyNode("foo"));
            myNodeRepository.save(new MyNode("bar"));
            myNodeRepository.save(new MyNode("car"));
    
            assertThat(myNodeRepository.findByNameLike("*ar*", new PageRequest(0, 20)).getNumberOfElements(), is(2));
            assertThat(myNodeRepository.findByNameLike("*o", new PageRequest(0, 20)).getNumberOfElements(), is(1));
            assertThat(myNodeRepository.findByNameLike("ca?", new PageRequest(0, 20)).getNumberOfElements(), is(1));
        }
    }

    Comment


    • #3
      Thank you for the prompt reply! That is working for me now.

      Comment


      • #4
        Sorry but I have to get back to this problem. Although the auto-repo is good for simple queries, I still need to use the regular expression for more complicated queries.

        For example:

        Code:
        public interface MyRepository extends GraphRepository<User>,
        	RelationshipOperationsRepository<User>,
        	NamedIndexRepository<User>{
        	
        	@Query(	"START user=node({0}) "+
        	"MATCH user-[:FRIENDS*1..2]-friends "+
        	"WITH user, friends "+
        	"MATCH friends-[:REL*1]->relatives "+
        	"WHERE relatives.name=~ /(?i).*{1}.*/ "+
        	"RETURN relatives")	
        	Set<User> findRelativesOfFriends(long userId, String search);
        }
        This works in the data browser, it returns a subset of relatives, but in java regardless of what search parameter I pass, it always returns the whole set.

        Am I doing something wrong?

        Comment


        • #5
          Originally posted by MichaelJaniak View Post
          Code:
          public interface MyRepository extends GraphRepository<User>,
          	RelationshipOperationsRepository<User>,
          	NamedIndexRepository<User>{
          	
          	@Query(	"START user=node({0}) "+
          	"MATCH user-[:FRIENDS*1..2]-friends "+
          	"WITH user, friends "+
          	"MATCH friends-[:REL*1]->relatives "+
          	"WHERE relatives.name=~ /(?i).*{1}.*/ "+
          	"RETURN relatives")	
          	Set<User> findRelativesOfFriends(long userId, String search);
          }
          This works in the data browser, it returns a subset of relatives, but in java regardless of what search parameter I pass, it always returns the whole set.
          Well, it actually does what you ask it; so it interprets that regex as
          Code:
          match .* one time, then match .* a bunch of times
          - the {1} is not substituted, it is taken literally

          Instead, do
          Code:
          @Query(	"START user=node({0}) "+
          	"MATCH user-[:FRIENDS*1..2]-friends "+
          	"WITH user, friends "+
          	"MATCH friends-[:REL*1]->relatives "+
          	"WHERE relatives.name=~ {1} "+
          	"RETURN relatives")	
          	Set<User> findRelativesOfFriends(long userId, String regex);
          
          ...
          
          myRepo.findRelativesOfFriends(42, "(?i).*my search string.*");
          Let me know if it works.

          Regards,

          Lasse

          Comment


          • #6
            That's perfect, works exactly like that, thank you for your help!

            Comment


            • #7
              Getting Neo4j cypher queries to work in java GraphRepository

              Sorry to flog a dead horse but getting cypher to work in the repository is often frustrating.

              This code works exactly as expected:

              Code:
              Set<Note> query =  repo.search(id, "(?i).*"+search+".*");
              ....
              
              @Query(
               "START user=node({0}) "
               "MATCH user-[:FRIEND*0..3]-friends, "+
               "friends-[:NOTE*1]->notes "+
               "WHERE notes.note=~ {1} "+
               "RETURN notes")
              Set<Note> search(long id, String search);
              But once I add more complexity, things start going tits up. This works in webadmin:

              Code:
              START user=node(548)
              MATCH user-[:FRIEND*0..3]-friends
              WITH distinct(friends) AS group, user
              MATCH group-[:NOTE*1]->notes
              WHERE notes.note=~ /(?i).*steve.*/
              OR notes.tags=~ /(?i).*steve.*/
              WITH notes, group, user
              MATCH path=shortestPath(user-[:FRIEND*]-group)
              RETURN notes, group, length(path)
              ORDER BY length(path) ASC
              If I hard code the regular expressions, this works in my repository:

              Code:
              Iterable<HashMap<String, Object>> query = repo.search2(id, "(?i).*"+search+".*");
              ....
              
                  @Query(
                  	"START user=node({0}) "+
                  	"MATCH user-[:FRIEND*0..3]-friends "+
                  	"WITH distinct(friends) AS group, user "+
                  	"MATCH group-[:NOTE*1]->notes "+
                  	"WHERE notes.note=~ /(?i).*steve.*/ "+
                  	"OR notes.tags=~ /(?i).*steve.*/ "+
                  	"WITH notes, group, user "+
                  	"MATCH path=shortestPath(user-[:FRIEND*]-group) "+
                  	"RETURN notes, group, length(path) "+
                  	"ORDER BY length(path) ASC " )
                  Iterable<HashMap<String, Object>> search2(long id, String search);
              But the moment I pass in the search variable...

              Code:
                  @Query(
                  	"START user=node({0}) "+
                  	"MATCH user-[:FRIEND*0..3]-friends "+
                  	"WITH distinct(friends) AS group, user "+
                  	"MATCH group-[:NOTE*1]->notes "+
                  	"WHERE notes.note=~ {1} "+
                  	"OR notes.tags=~ {1} "+
                  	"WITH notes, group, user "+
                  	"MATCH path=shortestPath(user-[:FRIEND*]-group) "+
                  	"RETURN notes, group, length(path) "+
                  	"ORDER BY length(path) ASC " )
                  Iterable<HashMap<String, Object>> search2(long id, String search);
              The query fails and I get a BadInputException, which makes no sense since the query works in webadmin, it works in java with a fixed regex, and works in java with a parameter, albeit for a smaller query.

              Again, any help would be much appreciated. Here is the stack trace if it's of any use

              Code:
                  Expected a parameter named 1 at
              BadInputException
                 org.neo4j.server.rest.repr.RepresentationExceptionHandlingIterable.exceptionOnHasNext(RepresentationExceptionHandlingIterable.java:51)
                 org.neo4j.helpers.collection.ExceptionHandlingIterable$1.hasNext(ExceptionHandlingIterable.java:61)
                 org.neo4j.helpers.collection.IteratorWrapper.hasNext(IteratorWrapper.java:42)
                 org.neo4j.server.rest.repr.ListRepresentation.serialize(ListRepresentation.java:58)
                 org.neo4j.server.rest.repr.Serializer.serialize(Serializer.java:75)
                 org.neo4j.server.rest.repr.MappingSerializer.putList(MappingSerializer.java:61)
                 org.neo4j.server.rest.repr.CypherResultRepresentation.serialize(CypherResultRepresentation.java:50)
                 org.neo4j.server.rest.repr.MappingRepresentation.serialize(MappingRepresentation.java:42)
                 org.neo4j.server.rest.repr.OutputFormat.format(OutputFormat.java:170)
                 org.neo4j.server.rest.repr.OutputFormat.formatRepresentation(OutputFormat.java:120)
                 org.neo4j.server.rest.repr.OutputFormat.response(OutputFormat.java:107)
                 org.neo4j.server.rest.repr.OutputFormat.ok(OutputFormat.java:55)
                 org.neo4j.server.rest.web.CypherService.cypher(CypherService.java:68)
                 java.lang.reflect.Method.invoke(Method.java:601)
                 org.neo4j.server.statistic.StatisticFilter.doFilter(StatisticFilter.java:62)
              Caused by:
              
              org.neo4j.rest.graphdb.RestResultException: Expected a parameter named 1 at
              BadInputException

              Comment


              • #8
                Sorry, you ran into a cypher problem, which will be fixed in this pull request: https://github.com/neo4j/community/pull/796

                So it will be available in Neo4j snapshot or in the next milestone or RC.

                Sorry for that.

                Michael

                Comment


                • #9
                  Ok, good to know. I can change my approach.

                  Comment


                  • #10
                    Originally posted by MichaelJaniak View Post
                    Ok, good to know. I can change my approach.
                    I need the same thing, how I can change my approach to the problem?, This remains unresolved: (

                    thank you very much

                    Comment


                    • #11
                      Originally posted by pedro.abalo View Post
                      I need the same thing, how I can change my approach to the problem?, This remains unresolved: (

                      thank you very much
                      Solved with lucene index in START clause and remove WHERE clause
                      Last edited by pedro.abalo; Jan 3rd, 2013, 10:29 AM.

                      Comment


                      • #12
                        Which version of SDN / Neo4j are you using Pedro?

                        Comment


                        • #13
                          Originally posted by MichaelHunger View Post
                          Which version of SDN / Neo4j are you using Pedro?
                          Spring data Neo4j 2.0.1 release with their respective dependencies maven, I think Neo4j 1.8 and to cypher-dsl version 1.7

                          but i solved changing where by index lucene in start clause

                          Thanks Michael!

                          Comment


                          • #14
                            What is your query ?

                            Comment


                            • #15
                              Originally posted by MichaelHunger View Post
                              What is your query ?
                              It's similar to this, i don't remember exact code now

                              START user=node:auto_index_node(idUser={0})
                              MATCH user-[rel]-car
                              WHERE car.model =~ {1} or car.color =~{2}
                              RETURN distinct(car)

                              where params {1} and {2} is a concated string with "*.termSearch*." (solution previous post)

                              the new query it's similar to this:

                              START user=node:auto_index_node(idUser={0}), car=node:index_car({1})
                              MATCH user-[rel]-car
                              RETURN distinct(car)

                              where param {1} is concated string with "model: termSearch* color: termSearch*"

                              in entityclass i have the index_car fulltext for my fields.

                              sorry for my english

                              thank Michael

                              Comment

                              Working...
                              X