Page 3 of 3 FirstFirst 123
Results 21 to 28 of 28

Thread: The difficult part of SDN Neo4j

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

    Default

    Ed, I appreciate your concern, can you raise an issue on that.

    I'm still wary. B/c fetching a subgraph can easily lead to fetching the whole graph even with a fetch-depth?

    I still think a fetch-depth parameter alone is not really enough, how do you specify where to apply it to? If the related nodes have related nodes again, to which of those will that fetch-depth apply (if any)? If you are related to the same node type (which again has the same fetch-depth annotated, should it keep the fetch-depth from the first (and decrease it) or should it start a new counter?

    Could you give some good (complex examples) how you would expect it to work out?

    I think semantics for a general fetch-depth are very vague.

    That's why I think a query annotated field makes much more sense here.

    But I'd love to discuss.

  2. #22
    Join Date
    May 2012
    Posts
    6

    Default Fetch-Depth

    Michael, thanks for the quick reply. Maybe it would help if I explain my use case, since there's a possibility I'm just not using the framework optimally.

    I have a social graph, so person objects connected to each other through "connections". My goal is to fetch one person and his immediate connections (depth 1), and process some data, modify the people and save the changes (all at once or one at a time, doesn't matter to me). My test set has my target user and 10 of his connections. To process all eleven seems to be slow, I haven't dug into why, but I'm assuming it's because I'm making at least 12 round trips to the DB via the rest interface (11 fetches and between 1 and 11 saves). I need a way to load all 11 objects at once. I think being able to specify a fetch-depth of 1 on the connection relationship would solve this, so

    Repository.findOne(id)

    Would return a fetch depth 1 for only the specified target node. Assuming the relationship is annotated that way.

    I did try to define an iterable "eagerConnection" and use a cypher query to load all of the first degree. Connections, but it looks like the result set is lazy loaded in that only the Id is populated, so I still have to call finfOne on each id. I want to get all connection with attributes in one query. Can this be done?

    In the future, it may be cool to specify a higher depth, but depth 1 is the most important, because if I don't have key attributes of friends (like name) I can't render anything usefull about the network with going back to neo4j N times. Am I missing a repository.findList([1, 2, 3, ...]) method or .loadAll(Set nodes) method somewhere?

    For higher depths I can see an arguement that this feature may be a little redundant with Traversals, but the difference between fetch depth 0 and 1 is crucial, at least to me.

    Thanks very much,
    Ed

  3. #23
    Join Date
    May 2012
    Posts
    107

    Default

    A thought on fetch-depth, or rather, an alternative: @Fetch works great for tree structures, as they help you define exactly the tree you want to get in your DTO. But as Ed is coming up against, with any kind of circular data structure it gets complicated.

    How about slicing a node two ways?

    By that I mean, I could define two or more DTOs depending on the use cases I have. For example, instead of Person->FRIEND->Person, I could do a mapping PersonStart->FRIEND->PersonEnd, with 2 use-case specific mappings - i.e. the PersonStart would have an @Fetch, PersonEnd would not.

    That way, you could "carve out" DTOs from your graph on a use-case by use-case basis. For the original problem, the @Fetch with depth only survives until the next use case which requires a different slice/ DTO.

    Practical? Not sure How does Cypher deal with this problem?

    Lasse

  4. #24
    Join Date
    Jan 2009
    Location
    Huntington Beach, CA
    Posts
    718

    Default

    Ed, that connection query is a very common query in a graph database. I have a query that would return a list of connections of connections from a person.

    You just write a Cypher query and it returns a full list of them all populated. It is just one query. And as far as saving, it is just changing those objects within a transaction.

    Here is what my repository method looks like

    Code:
    @Query("start user=node({0}) " +
                "match user-[:"+ User.FRIEND+"]->friends-[:"+ User.FRIEND+"]->friendsOfFriends " +
                "return friendsOfFriends " +
                "order by count(*) desc, friendsOfFriends.lastName asc")
    public Page<User> findFriendsOfFriends(User user, Pageable pageable);
    and in my Service I just call that method and I get a list of Users fully populated. (Note I use ThreadLocal to store page size and number and get it in my service method, but I am not showing that code here, also the User is the user logged in, so it already in my Spring Security Context. Also not shown is the creation of my ListOfDomains object, but none of that is necessary to demonstrate how simple a query like that is. No fetch depth needed.)

    Code:
    @Service
    public class UserServiceImpl implements UserService {
    
        @Autowired
        private UserRepository userRepository;
    
        @Transactional
        public ListOfDomains<User> findFriendsOfFriends() {
            Page<User> foff = userRepository.findFriendsOfFriend(userRepository.getUserFromSession(), PageRequestHandler.getPageRequest());
         
            // Loop through Users and change properties.
            …….
        }
    }
    At this time, should these questions be posted in another topic. They are very off topic from the original thread I created.

    Thanks

    Mark

    Mark

  5. #25
    Join Date
    May 2012
    Posts
    6

    Default Fetch-Depth

    Mark,

    That is the same query that I wrote except I didn't include the Pageable object. But what I find is the using the embedded neo4j with my query works fine, and using the rest API seems to only load the id property of the objects. I still need to call findOne on each id to load the full object.

    Ed

  6. #26
    Join Date
    Jan 2009
    Location
    Huntington Beach, CA
    Posts
    718

    Default

    Really? Yeah, I am just using the embedded and everything is populated. I wonder why the REST Api would would differently?

    Good Luck

    Mark

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

    Default

    That should not happen, if you look at the REST server response the full information is there so it should also populate the entities.

    What is missing from the object, each (primitive) property or just the relationships?

    I'll try to set up a testcase to investigate, can you raise an JIRA issue in the meantime?

  8. #28
    Join Date
    May 2012
    Posts
    6

    Default Fetch-Depth

    It was a primitive, name, which was a String. I'll write a short unit test to confirm, and include sample code/query in the JIRA.

    Thanks,
    Ed

    Quote Originally Posted by MichaelHunger View Post
    That should not happen, if you look at the REST server response the full information is there so it should also populate the entities.

    What is missing from the object, each (primitive) property or just the relationships?

    I'll try to set up a testcase to investigate, can you raise an JIRA issue in the meantime?

Posting Permissions

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