Page 2 of 3 FirstFirst 123 LastLast
Results 11 to 20 of 28

Thread: The difficult part of SDN Neo4j

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

    Default

    user-[host?:HOSTS]->event

    is an optional match which results in host being non-null for a successful match and null for a non-existing relationship (like an outer join in SQL). And as both user and event are already bound it will not spread the result to more than this single user + single event.

    For your second questions, this will fetch all the relationships of the type ITEMS_SIGNED_UP_FOR and for the end nodes (signedUpToBringToEvent) it will also do the "optional relationship" check.

  2. #12
    Join Date
    Jan 2009
    Location
    Huntington Beach, CA
    Posts
    718

    Default

    I got the first cypher query to work.

    I had downloaded and unzipped the Neo4j 1.6 Community Server. So I copied my db from my Tomcat dir to the unzipped servers data directory and got it running with the web console. Took some time to figure the console out, when to the Power Tool console and learned some of that. Took the query I had on the repo method and tried to run it on the Power Tool console. Tweaked it to get it to return the correct results.

    Had to change "match user-[r]->event" to "match user-[r]-event" since the Invited relationship is in the other direction. so I needed it to check both directions. The ResultSet had the correct data that I need.

    I even got the @MapResult to populate the data, sort of. In debugging I noticed that I couldn't view any of the data that the returned object with @MapResult is a proxy, which makes sense since that object was just an interface. But now I am wondering when the data gets retrieved via the proxy. I guess just call the getters, and Jackson will call the getters and render them into json to send back to the client.

    Thanks

    Mark

  3. #13
    Join Date
    Jan 2009
    Location
    Huntington Beach, CA
    Posts
    718

    Default

    Unfortunately, it doesn't look like I am able to get json from the proxies.

    "Could not write JSON: No serializer found for class $Proxy69 and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: com.perfectworldprogramming.eventgate.wrappers.Lis tOfDomains["domainObjects"]->java.util.ArrayList[0])"

    the disable part is probably not a solution as there are no empty beans.

    Do I have to implement those ResultConverters??? I like the annotations with @MapResult. Much less code to write.

    Thanks

    Mark

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

    Default

    I don't think I can use those ResultConverters. I am not using the template to run queries, I have @Query on my repo interface methods.

    Also earlier you had said something about moving the calculate method my ListOfDomain class. The ListOfDomains is just a wrapper class to store the List<T> domain objects, so all types for different requests not just this one, so a calculate method would be too specific for one use case to be put into the generic ListOfDomain class. But we already have that solved with the cool Cypher query.

    The service class now would look like this for that first use case

    Code:
        @Override
        public ListOfDomains<EventItemForAccountPage> getListOfEventsForAccount() {
            ListOfDomains<EventItemForAccountPage> listOfDomains = 
                        new ListOfDomains<EventItemForAccountPage>();
            
            Collection<EventItemForAccountPage> events = 
                        eventRepository.getEventsForAccountPage(userRepository.getUserFromSession().getNodeId());
            
            listOfDomains.setDomainObjects(new ArrayList<EventItemForAccountPage>(events));
            listOfDomains.setType("Events you are involved with.");
            return listOfDomains;
        }
    EventItemForAccountPage is just the EventListItem with a different name so I could have my old approach and the new approach in my code at the same time, till the new way works all the way to the UI.

    Thanks

    Mark

  5. #15
    Join Date
    Jan 2009
    Location
    Huntington Beach, CA
    Posts
    718

    Default

    In the Web console Power Tool I tried

    Code:
    start user=node({user}), event=node({eventId})
    match user-[host?:HOSTS]->event,
    event-[:ITEMS_NEEDED]->neededItem-[:ITEM]->item,
    event-[:ITEMS_SIGNED_UP_FOR]-> signedUpToBringToEvent-[userSignedUp?:USER]->user
    return host!=null as isHost, ID(neededItem) as neededItemId, neededItem.quantity as quantity, item.name as itemName,  
    userSignedUp!=null as currentUserSignedUp, ID(signedUpToBringToEvent) as itemSignedUpId
    and similar variations. It looks like Neo4j doesn't like things like "host!=null as isHost" I got messages that I hurt some puppies or like that.

    Code:
    neo4j-sh (0)$ start user=node(33), event=node(53) match user-[host?:HOSTING]-event, event-[?:ITEMS_NEEDED_FOR_EVENT]-neededItem, event-[?:ITEMS_SIGNED_UP_FOR]-signedUpToBringToEvent-[userSignedUp?:USER_SIGNED_UP]-user return host!=null as isHost, ID(neededItem) as neededItemId, neededItem.quantity as quantity, ID(signedUpToBringToEvent) as itemSignedUpId
    ==> SyntaxException: string matching regex `\z' expected but `!' found
    ==> Unfortunately, you have run into a syntax error that we don't have a nice message for.
    ==> By sending the query that produced this error to cypher@neo4j.org, you'll save the
    ==> puppies and get better error messages in our next release.
    ==> 
    ==> Thank you, the Neo4j Team.
    When I removed those in the return statement the query would run. Not actually returning any results, but would not be the data I was looking for.

    Code:
    neo4j-sh (0)$ start user=node(33), event=node(53) match user-[host?:HOSTING]-event, event-[:IITEMS_NEEDED_FOR_EVENT]-neededItem, event-[:ITEMS_SIGNED_UP_FOR]-signedUpToBringToEvent-[userSignedUp?:USER_SIGNED_UP]-user return ID(neededItem) as neededItemId, neededItem.quantity as quantity, ID(signedUpToBringToEvent) as itemSignedUpId
    ==> +------------------------------------------+
    ==> | neededItemId | quantity | itemSignedUpId |
    ==> +------------------------------------------+
    ==> +------------------------------------------+
    ==> 0 rows, 1 ms
    ==> 
    neo4j-sh (0)$ start user=node(33), event=node(53) match user-[host?:HOSTING]-event, event-[:ITEMS_NEEDED_FOR_EVENT]-neededItem, event-[:ITEMS_SIGNED_UP_FOR]-signedUpToBringToEvent-[userSignedUp?:USER_SIGNED_UP]-user return ID(neededItem) as neededItemId, neededItem.quantity as quantity, ID(signedUpToBringToEvent) as itemSignedUpId
    ==> +------------------------------------------+
    ==> | neededItemId | quantity | itemSignedUpId |
    ==> +------------------------------------------+
    ==> +------------------------------------------+
    ==> 0 rows, 35 ms
    ==> 
    neo4j-sh (0)$ start user=node(33), event=node(53) match user-[host?:HOSTING]-event, event-[?:ITEMS_NEEDED_FOR_EVENT]-neededItem, event-[?:ITEMS_SIGNED_UP_FOR]-signedUpToBringToEvent-[userSignedUp?:USER_SIGNED_UP]-user return ID(neededItem) as neededItemId, neededItem.quantity as quantity, ID(signedUpToBringToEvent) as itemSignedUpId
    ==> EntityNotFoundException: The property 'quantity' does not exist on Node[47]
    The neededItem is a Relationship object. Well, I think I know where to fix that.

    "event-[?:ITEMS_NEEDED_FOR_EVENT]-neededItem"

    should be

    "event-[neededItem?:ITEMS_NEEDED_FOR_EVENT]-item"

    But I still get the puppies message with the !=null stuff for some reason.

    Thanks

    Mark

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

    Default

    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

  7. #17
    Join Date
    Jan 2009
    Location
    Huntington Beach, CA
    Posts
    718

    Default

    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

  8. #18
    Join Date
    Jan 2009
    Location
    Huntington Beach, CA
    Posts
    718

    Default

    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

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

    Default

    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?

  10. #20
    Join Date
    May 2012
    Posts
    6

    Default 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

Posting Permissions

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