Announcement Announcement Module
Collapse
No announcement yet.
The difficult part of SDN Neo4j Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • #16
    I fixed the event to neededItem to item, but still not getting results. Most recent on Power Tool is

    Code:
    neo4j-sh (0)$ start user=node(33), event=node(53) match user-[host?:HOSTING]->event, event-[neededItem?:ITEMS_NEEDED_FOR_EVENT]->item, event-[?:ITEMS_SIGNED_UP_FOR]->signedUpToBringToEvent-[userSignedUp?:USER_SIGNED_UP]->user return ID(neededItem) as neededItemId, neededItem.quantity as quantity, item.description as itemName, ID(signedUpToBringToEvent) as itemSignedUpId
    ==> MatchError: null
    If I get that to return results, I'll try to bring back the !=null part.

    Thanks

    Mark

    Comment


    • #17
      This is as far as I have gotten and I am now stuck making this work.

      Code:
      start user=node(33), event=node(53) 
      match user-[host?:Hosting]->event, 
               event-[neededItem:ITEMS_NEEDED_FOR_EVENT]->item, 
               event<-[?:EVENT_SIGNED_UP_FOR_ITEM]-signedUpToBringToEvent-[userSignedUp?:USER_SIGNED_UP]->user 
      return host != null as isHost, 
               ID(item) as neededItemId, 
               neededItem.quantity as quantity, 
               item.description as itemName, 
               userSignedUp != null as currentUserSignedUp, 
               ID(signedUpToBringToEvent) as itemSignedUpId
      So there were some relationship names in the query before that were non-existent, they had other names.

      But I do see a disconnect and why it might be that the query doesn't work. In the match portion, the second and third part are not related in the query. But they have to be related. Meaning I have an event with many items needed, 2nd part of the match. The user may signup (3rd part of the match)to any of those items, not necessarily to that particular neededItem item that is returned in the 2nd part of the match. To userSignedUp!= null has to be specific for the item returned for item in the second part.

      So if the second part returns Item Pepsi, but the third part returns items the user signed up and none of them are Pepsi, the userSignedUp !=null will result in true, which is NOT correct.

      I guess I could add to the third part but this is confusing

      event<-[?:EVENT_SIGNED_UP_FOR_ITEM]-signedUpToBringToEvent-[userSignedUp?:USER_SIGNED_UP]->user<-[userSignedUp:USER_SIGNED_UP]-signedUpToBringToEvent<-[:ITEM_SIGNED_UP_FOR_EVENT]-item

      Ack

      Mark

      Comment


      • #18
        At this point, the data that is needed, it cannot be done in just one Cypher query. It just isn't possible since there is a big fork in the traversal where we have to go down those paths and in the end get them, and also values of comparison among the forks.

        So, for that use case, I am keeping the code I have.

        Mark

        Comment


        • #19
          Of course as I don't have your relationship-names I just made some up

          Oftentimes it is sensible to explore partial queries with cypher and when they return the required results then combining them to a more complex pattern.

          In your case it might be sensible to have two queries, first a simpler one that returns just the one row with the "boolean" information, and a second one for the items?

          Comment


          • #20
            Fetch-Depth

            Michael, I, for one, would love to see a fetch-depth parameter. Especially on the @Fetch annotation, but having it at query time would be additionally useful. Currently, if my graph is a social network, I can't use @Fetch at all. So I need to define the connections Set with lazy loading, then define a Cypher iterable for eager first degree loading. It just seems like this leads to ugly code since each relationship will have two methods to call to get the connections. I think allowing a Fetch depth setting can decrease code bloat significantly.

            Wonderful product by the way. Thank you very much for building it.

            Ed

            Comment


            • #21
              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.

              Comment


              • #22
                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

                Comment


                • #23
                  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

                  Comment


                  • #24
                    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

                    Comment


                    • #25
                      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

                      Comment


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

                        Good Luck

                        Mark

                        Comment


                        • #27
                          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?

                          Comment


                          • #28
                            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

                            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?

                            Comment

                            Working...
                            X