How to handle relations that can also potentially qualify as an entity


(Nick Clark) #1

New to Graph DB in general, and really excited about Neo4j! But running in an issue with knowing how think/reason about some data in Neo4j.

Lets say, in a normal DB I have three tables: Airplanes, Airports, and Jobs. Airports have many Jobs going to other Airports. Jobs have some data like 'cost', cargoType, fromAirport, toAirport, and airplaneId. One of my main goals will be to be able to query for the shortest route, over a specifed number of hops, that will make the most money. The answer initially seemed easy. Just do (Airport)-[:Job]->(Airport). The biggest thing that is confusing me right now, is that technically a Job is a noun which implies an Entity. Furthermore, Job's have an Aircraft ID which means That we have a third relation playing in. So I tried another method: Make jobs an entity: (Airport)-[DEPARTS]->(Job)-[:ARRIVES]->((Airport), (Airplane)-[:IS_FLYING]->(Job). But this seems weird to query. In the first case, I could have just (a:Airport)-[:Job*..12]->(b:Airport), but in this last case, I don't yet know how to do that.

Still learning... so haven't even got to the meat, which is concocting a query that shows the most profitable route considering the number of requested hops.

Anyway, appreciate any help you fine folks can lend!


(Jiropole) #2

I think your gut feeling about making Job an entity is correct. While I don't think I fully understand your context, here is one design that might provide another way of thinking about it.

CREATE (ap1:Airport {name: 'LAX'}), (ap2:Airport {name: 'SFO'}), (ap3:Airport {name: 'MSP'}),
    (j1: Job {cargoType: 'pallet'}), (j2: Job {cargoType: 'case'}),
    (t1: Trip {cost: 1200}), (t1)-[:HAULING]->(j1), (t1)-[:DEPARTING]->(ap1), (t1)-[:ARRIVING]->(ap2),
    (t2: Trip {cost: 800}), (t2)-[:HAULING]->(j1), (t2)-[:DEPARTING]->(ap2), (t2)-[:ARRIVING]->(ap3),
    (t3: Trip {cost: 600}), (t3)-[:HAULING]->(j2), (t3)-[:DEPARTING]->(ap1), (t3)-[:ARRIVING]->(ap3)
RETURN *

Here, Airports, Jobs and Trips are connected to capture the cost of HAULING given Jobs between given Airports. Try running this to see the graph; maybe this offers you the flexibility you're looking for.


(Nick Clark) #3

So, ya... similar idea. I guess I don't yet understand how I can do a "highest profit in x hops" query. I'm thinking algo.spanningTree.kmax should work. But I think you need to have a single relationship connecting each airport since you need a property on the relationship to get the weight. Whereas, if Job is an Entity, you can't get weights from it. Maybe I should create, in addition to the above mentioned schema, an additional relationship.

Here's an example idea:
image

CREATE (ap1:Airport {name: 'LAX'}), (ap2:Airport {name: 'SFO'}), (ap3:Airport {name: 'MSP'}),
    (j1:Job {cargoType: 'pallet', qty: 1}), (j2:Job {cargoType: 'case', qty: 2}),
    (j3:Job {cargoType: 'passenger', qty: 3}), (j4:Job {cargoType: 'passenger', qty: 1}),
    (j5:Job {cargoType: 'passenger', qty: 1}),
    (ap1)-[:JOB {cost: 100, jobId: id(j1)}]->(ap2), (ap1)-[:DEPARTING]->(j1), (j1)-[:ARRIVING]->(ap2),
    (ap2)-[:JOB {cost: 200, jobId: id(j2)}]->(ap3), (ap2)-[:DEPARTING]->(j2), (j2)-[:ARRIVING]->(ap3),
    (ap2)-[:JOB {cost: 300, jobId: id(j3)}]->(ap1), (ap2)-[:DEPARTING]->(j3), (j3)-[:ARRIVING]->(ap1),
    (ap2)-[:JOB {cost: 400, jobId: id(j4)}]->(ap3), (ap2)-[:DEPARTING]->(j4), (j4)-[:ARRIVING]->(ap3),
    (ap3)-[:JOB {cost: 500, jobId: id(j5)}]->(ap2), (ap3)-[:DEPARTING]->(j5), (j5)-[:ARRIVING]->(ap2)
RETURN *

Using this, I think I should be able to use an alg to find that the most profitable 1 hop route is (SFO)-[400+200]->(MSP) and most profitable 3 hop (SFO)-[400+200]->(MSP)-[500]->(SFO)-[300]->(LAX) (Notice that you can combine multiple jobs going in the same direction, so I suppose I'll have to perhaps combine that one somehow). Still trying to figure this out, allPairsShortestPath is close... but I'm still figuring that out. It's likely that there is no permanent way to just look at all records and find qualifying routes without some how scoping it first...