Page 1 of 2 12 LastLast
Results 1 to 10 of 18

Thread: Getting Neo4j cypher queries to work in java GraphRepository

  1. #1
    Join Date
    Aug 2012
    Location
    New York, NY
    Posts
    9

    Default 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. #2
    Join Date
    May 2012
    Posts
    107

    Default

    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));
        }
    }

  3. #3
    Join Date
    Aug 2012
    Location
    New York, NY
    Posts
    9

    Default

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

  4. #4
    Join Date
    Aug 2012
    Location
    New York, NY
    Posts
    9

    Default

    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?

  5. #5
    Join Date
    May 2012
    Posts
    107

    Default

    Quote 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

  6. #6
    Join Date
    Aug 2012
    Location
    New York, NY
    Posts
    9

    Default

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

  7. #7
    Join Date
    Aug 2012
    Location
    New York, NY
    Posts
    9

    Default 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

  8. #8
    Join Date
    Jan 2011
    Location
    Dresden, Germany
    Posts
    525

    Default

    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

  9. #9
    Join Date
    Aug 2012
    Location
    New York, NY
    Posts
    9

    Default

    Ok, good to know. I can change my approach.

  10. #10
    Join Date
    Oct 2012
    Location
    Madrid, ES
    Posts
    5

    Default

    Quote 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

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •