2017-04-02 5 views
1

tout le monde! J'ai une base de données Neo4j qui contient des informations sur les visiteurs qui visitent un certain nombre de points de contrôle à des moments spécifiques. Les visiteurs, les visites et les points de contrôle sont représentés comme des nœuds. Chaque visiteur est identifié par l'adresse MAC de son appareil, chaque point de contrôle a un identifiant unique.La requête de chiffrement Neo4j avec fonction d'agrégat renvoie un résultat incomplet

Chaque nœud de visite contient une propriété EnterTime, qui est l'heure (nombre de millisecondes depuis 1970) où le visiteur avec une adresse MAC spécifique est remarqué pour la première fois près du point de contrôle respectif.

Remarque: la durée d'une visite doit être calculée comme la différence entre EnterTime de la prochaine visite et le temps de séjour de cette visite. Chaque point de contrôle peut être visité plus d'une fois.

La base de données est créée avec cette requête Cypher:

//Create visitors: 
CREATE (Visitor1: Visitor {MAC:'00:0a:95:9d:68:16'}) 
CREATE (Visitor2: Visitor {MAC:'00:0a:95:9d:68:17'}) 
CREATE (Visitor3: Visitor {MAC:'00:0a:95:9d:68:18'}) 

//Create CheckPoints: 
CREATE (CheckPoint1: CheckPoint {CheckPointId: 1}) 
CREATE (CheckPoint2: CheckPoint {CheckPointId: 2}) 
CREATE (CheckPoint3: CheckPoint {CheckPointId: 3}) 
CREATE (CheckPoint4: CheckPoint {CheckPointId: 4}) 
CREATE (CheckPoint5: CheckPoint {CheckPointId: 5}) 


//Create visits: 
//by visitor 1: 
CREATE (Visitor1)-[:MAKES]->(Visit1: Visit {EnterTime: 1488358800000})-[:TO]->(CheckPoint1) 
CREATE (Visitor1)-[:MAKES]->(Visit2: Visit {EnterTime: 1488359400000})-[:TO]->(CheckPoint2) 
CREATE (Visitor1)-[:MAKES]->(Visit3: Visit {EnterTime: 1488361200000})-[:TO]->(CheckPoint3) 
CREATE (Visitor1)-[:MAKES]->(Visit4: Visit {EnterTime: 1488363600000})-[:TO]->(CheckPoint4) 
CREATE (Visitor1)-[:MAKES]->(Visit5: Visit {EnterTime: 1488364800000})-[:TO]->(CheckPoint5) 
CREATE (Visitor1)-[:MAKES]->(Visit6: Visit {EnterTime: 1488365400000})-[:TO]->(CheckPoint1) 

//by visitor 2: 
CREATE (Visitor2)-[:MAKES]->(Visit7: Visit {EnterTime: 1488358800000})-[:TO]->(CheckPoint1) 
CREATE (Visitor2)-[:MAKES]->(Visit8: Visit {EnterTime: 1488360300000})-[:TO]->(CheckPoint4) 
CREATE (Visitor2)-[:MAKES]->(Visit9: Visit {EnterTime: 1488362400000})-[:TO]->(CheckPoint2) 
CREATE (Visitor2)-[:MAKES]->(Visit10: Visit {EnterTime: 1488363000000})-[:TO]->(CheckPoint1) 

//by visitor 3: 
CREATE (Visitor3)-[:MAKES]->(Visit11: Visit {EnterTime: 1488353820000})-[:TO]->(CheckPoint1) 
CREATE (Visitor3)-[:MAKES]->(Visit12: Visit {EnterTime: 1488354600000})-[:TO]->(CheckPoint4) 
CREATE (Visitor3)-[:MAKES]->(Visit13: Visit {EnterTime: 1488358200000})-[:TO]->(CheckPoint3) 
CREATE (Visitor3)-[:MAKES]->(Visit14: Visit {EnterTime: 1488359700000})-[:TO]->(CheckPoint1) 

Je vous écris une requête Cypher pour trouver le temps total de visites à chaque point de contrôle. J'essaie celui-ci:

match (vr: Visitor)-->(v1: Visit)-->(cp1: CheckPoint), 
(vr)-->(v2: Visit)-->() 
where v2.EnterTime > v1.EnterTime 
with cp1.CheckPointId as CheckPointId, 
    v1.EnterTime as EnterTime, 
    min((v2.EnterTime - v1.EnterTime)/60000) as visit_duration 
return CheckPointId, sum(visit_duration) as total_visit_duration 
order by CheckPointId; 

Le résultat devrait être:

cp1 - 48 min 
cp2 – 40 min 
cp3 – 65 min 
cp4 – 115 min 
cp5 – 10 min 

Mais ma requête renvoie un résultat incorrect:

cp1 - 23 min 
cp2 – 40 min 
cp3 – 65 min 
cp4 – 115 min 
cp5 – 10 min 

De toute évidence, l'erreur est que la longueur la visite du visiteur (mac == 00: 0a: 95: 9d: 68: 17) au point de contrôle avec id == 1 n'est pas prise en compte. Mais c'est ma conjecture.

Quel est le problème avec ma requête? Comment peut-il être amélioré pour retourner le bon résultat?

Votre aide sera grandement appréciée! Merci!

Répondre

2

Je pense que ce que vous cherchez est le suivant:

match()<--(v2:Visit)<--(vr: Visitor)-->(v1: Visit)-->(cp1: CheckPoint) 
where v2.EnterTime > v1.EnterTime 
with vr, 
cp1.CheckPointId as CheckPointId, 
v1.EnterTime as EnterTime, 
min((v2.EnterTime - v1.EnterTime)/60000) as visit_duration 
return CheckPointId, sum(visit_duration) as total_visit_duration 
order by CheckPointId; 

I ajouté vr dans with déclaration. Groupes Cypher par toutes les valeurs que vous mettez dans l'instruction with. La raison pour laquelle votre code n'a pas fonctionné est parce que v1.EnterTime pour le point de contrôle 1 pour les visiteurs 1 et 2 est la même chose. Parce que vous avez seulement et CheckpointID dans with déclaration, chiffré par EnterTime et ainsi parce que vous avez le min(v2.EnterTime - v1.EnterTime) il a juste pris le plus petit et n'a pas utilisé les deux. Maintenant que nous introduisons Visitor dans l'instruction with, il va regrouper par visiteur également, ce qui résout notre problème, si deux personnes démarrent le même point de contrôle en même temps.

Espérons que cela aide

+0

Merci! Il a résolu le problème! Je vous suis très reconnaissant pour votre aide! Espérons que cela sera utile à d'autres personnes qui luttent avec Neo4j et cypher. – zavanton