cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

Distance filtering between two properties

leelandclay
Graph Buddy

I'm writing a dating app where members can specify how far away they're willing to travel for a date. Each :Person object contains a location and distance property. The location property is a Point object and the distance property is an integer that represents distances in miles (10, 15, 30, 50, 100, 250, 500, 999, 1001). The 999 property represents that the member is open to dates "Anywhere" and 1001 equates to only in their state/country.

I have the query working for the miles entries (10-500), however I'm trying to figure out how to do the 999 and 1001.

My current query is:

MATCH (me:Person {userId: $userId})
MATCH (p:Person) WHERE distance(me.location, p.location) <  p.distance * $distanceMultiplier 
AND distance(me.location, p.location) < $distance * $distanceMultiplier

If the person doing the query has their distance set as Anywhere, I simply do not include the AND clause. I can easily change which clauses get added via the API code to handle the user's settings for the person who is calling the method. My problem is being able to get properties from the result set and possibly change the AND clause based on it. For instance:

If the person making the query is open to anywhere, Person objects for people that are in a different Country/State that don't want to go that far should not show up. In order to do that, I would need to look into the Person object to get their distance property and then if that Person object has a distance of 999 or 1000, then change the query for that.

I hope this makes sense. 🙂

*** Edit ***
Just want to add that if I'm going about this the wrong way and need to change the schema, I can do that.

1 REPLY 1

leelandclay
Graph Buddy

I think I've found the only way to do this. Essentially, I'm creating multiple queries and unioning them together into a single resultset. I'm using apoc.cypher.run in order to run the UNION statements and get back the resultset so that I can then filter it. The queries are all based on the distance value of the :Person node (1001, 1000, 999 or anything else). I then use an if statement within the API to determine which group of queries to start with. As an example, this is the scenario where the person performing the query has set a specific distance setting (anything less than 999):

CALL apoc.cypher.run(' 
MATCH (me:Person { userId: $userId}) 
MATCH (p:Person) WHERE p.distance < 999 AND distance(me.location, p.location) < $distanceMeters AND (p.distance * $distanceMultiplier) > distance(me.location, p.location) 
RETURN p 
UNION 
MATCH (me:Person { userId: $userId}) 
MATCH (p:Person) WHERE p.distance = 999 AND distance(me.location, p.location) < $distanceMeters 
RETURN p 
UNION MATCH (me:Person { userId: $userId}) 
MATCH (p:Person) WHERE p.distance = 1000 AND p.state = me.state 
RETURN p 
UNION 
MATCH (me:Person { userId: $userId}) 
MATCH (p:Person) WHERE p.distance = 1001 AND p.country = me.country 
RETURN p ', 
{  userId: $userId, distanceMeters: $distanceMeters, distanceMultiplier: $distanceMultiplier } ) yield value 
WITH value.p as p