Collect vertices whose edges point at the same vertex

Hi, I am just starting to study graphs and I am somewhat stuck in a problem:

A–>B–>C–>D
How to know the users (A) that made all of its orders (B) from clients ( C) that are in the same country (D)?

I am having problems understanding how I can fulfill the last condiction and select only the vertices from A that end up pointing at only one vertex in D (whoever this may be).

Thank you in advance.

@JsolarC Based on the information provided I went ahead and designed a small solution to show you what I would do.

You mentioned that you are using location information (country). There is a concept of Geo-Trees in Graphs. Geo-Tree’s can help with filtering information by crawling along edges. Please refer to the right side of this image:

Next, let’s look at how you would go about pulling that information. I’m using v1 syntax. v2 syntax you could simply state this in an expression, but v1 helps you understand the journey.

Getting Started

To get started I want to pass those parameters, “USA” for the country and “Amazon” for the client.

CREATE QUERY findOrders(VERTEX<Client> client, VERTEX<Country> country) FOR GRAPH Shipments { `

Next, I want to accumulate the users and their orders into lists

ListAccum<EDGE> @@userOrders;

After this, we will start with our seed which is “USA” in our case. Then we will find only the addresses (of users) that are located in the “USA”

Seed = {country};
  AddressInCountry = SELECT tgt FROM Seed:s -(ADDRESS_IN_COUNTRY:e)- Address:tgt;

After we have those let’s find the “Users” belonging to those “USA” addresses:

  UsersInCountry = SELECT tgt FROM AddressInCountry:s -(ADDRESS_OF_USER:e)- Users:tgt;

Okay now we have all the users that are located in the “USA”, but we want only the Users that belong to Client “Amazon”. To do this we will take a peek and filter our users that only belong to that client “Amazon” with a WHERE clause.

  ClientUsers = SELECT s FROM UsersInCountry:s -(HAS_CLIENT:e)- Client:tgt WHERE tgt == client;

Lastly, let’s use an ACCUM and our ListAccum to grab all those orders belonging to the users.

  GetOrder = SELECT tgt FROM ClientUsers:s -(PLACES_ORDER:e)- Orders:tgt ACCUM @@userOrders += e; 

Final Product

This is what we end up with when putting the pieces together.

CREATE QUERY findOrders(VERTEX<Client> client, VERTEX<Country> country) FOR GRAPH Shipments { 
  ListAccum<EDGE> @@userOrders;
  
  Seed = {country};
  
  AddressInCountry = SELECT tgt FROM Seed:s -(ADDRESS_IN_COUNTRY:e)- Address:tgt;
  UsersInCountry = SELECT tgt FROM AddressInCountry:s -(ADDRESS_OF_USER:e)- Users:tgt;
  ClientUsers = SELECT s FROM UsersInCountry:s -(HAS_CLIENT:e)- Client:tgt WHERE tgt == client;
  GetOrder = SELECT tgt FROM ClientUsers:s -(PLACES_ORDER:e)- Orders:tgt ACCUM @@userOrders += e; 
  
    
  PRINT @@userOrders; 
}

Output

When executing the query with inputs of “USA” and “Amazon” we get the following:

1 Like

This query intend to output all countries and the list of related users (via order & client vertices) . This is still a psuedo-code as this is written without creating the underlying data model.

syntax V2

SetAccum<STRING> @FinalUserSet;

CountryWUsersSet = SELECT c
FROM user:u1-(ORDERED_FROM>:o1)-client:cl1-(LIVES_IN>:l1)-country:c-(<LIVES_IN:l1)-client:cl2-(<ORDERED_FROM:o2)-user:u2
WHERE u1.user_id != u2.user_id
AND   cl1.client_id == cl2.client_id
ACCUM c.@FinalUserSet += u1.user_id, c.@FinalUserSet += u2.user_id 
 
PRINT  CountryWUsersSet
2 Likes

@Jon_Herke Thank you for your detailed reply.

I think I didn’t explain myself very well, since the logic of your proposal goes in a different direction than the one I intended.

In my scenario, there is no direct connection between country and users (only the “address/country” of the clients is known).

Furthermore, a client can only belong to one country but a user can have multiple clients. Because of this, my question is: which users only bought from the same country? Such that my end result is the set of users that always bought from one and only one country. Following:

User --> Client --> Country

Thank you again in advance for your reply.

@tigergraphuser thank you for your reply.

I do not understand where, within the pseudo-code you wrote, it can be secured that there are not users that may be listed under two or more different countries. Since my idea is to find the clients that only buy from one and only one country.

Again thank you in advance for your reply.

@JsolarC

Entity Relationships:

User to Client : 1 to Many
Client to Country : 1 to 1
i.e User to Country : 1 to Many

Graph Schema

image

vertices:

Users Set will be similar to this and User ‘John’ would be final output

image

G-SQL Query

CREATE QUERY user_country_test() FOR GRAPH user_country syntax V2 { 
  
  SumAccum<INT> @CountryCount;
  MapAccum<STRING, SetAccum<STRING>> @@UserCountryMap;

  UserSet = SELECT u
  FROM user:u-(orders_from>:o)-client:cl-(lives_in>:l)-country:c
  ACCUM  u.@CountryCount += 1,
       @@UserCountryMap += (u.user_name -> (c.country_name));
  
  PRINT "**Users who ordered from one-and-only-one country**";
  FOREACH (userName, countryList) in @@UserCountryMap DO
	  	IF countryList.size() == 1 THEN
        PRINT userName;
      END;
  END;       

  //PRINT UserSet;
  PRINT "User with countries:", @@UserCountryMap;
}

Output:

  {
"userName": "John"
  },
  {
"\"User with countries:\"": "User with countries:",
"@@UserCountryMap": {
  "John": [
    "Canada"
  ],
  "Penny": [
    "China",
    "USA"
  ],
  "Tom": [
    "S. Africa",
    "USA"
  ],
  "user_name": [
    " country_name"
  ]
}