2014-07-07 2 views
1

J'ai un serveur neo4j embarqué avec rubis sur rails.Accélération de la requête cypher neo4j

Ce sont les configurations:

neostore.nodestore.db.mapped_memory=25M 
neostore.relationshipstore.db.mapped_memory=240M 
neostore.propertystore.db.mapped_memory=230M 
neostore.propertystore.db.strings.mapped_memory=1200M 
neostore.propertystore.db.arrays.mapped_memory=130M 

wrapper.java.initmemory=1024 
wrapper.java.maxmemory=2048 

Il y a environ 15lakh nœuds de cinéma. La requête ci-dessous prend environ 5secs pour s'exécuter.

MATCH (movie:Movie) 
WITH movie, toInt(movie.reviews_count) + toInt(movie.ratings_count) AS weight 
RETURN movie, weight as weight 
ORDER BY weight DESC 
SKIP skip_count 
LIMIT 10 

Ici, le skip_count varie comme le défilement de l'utilisateur pour les résultats.

et cette autre requête qui vise à obtenir les films d'un réalisateur particulier prend environ 9secs

MATCH (movie:Movie) , (director:Director)-[:Directed]->(movie) 
WHERE director.name =~ '(?i)DIRECTOR_NAME' 
WITH movie, toInt(movie.ratings_count) * toInt(movie.reviews_count) * toInt(movie.rating) AS total_weight 
RETURN movie, total_weight 
ORDER BY total_weight DESC, movie.rating DESC 
LIMIT 10 

Comment puis-je réduire le temps d'exécution de la requête?

Répondre

2

en ce qui concerne la première requête:

Vous pourriez faire le poids de la commande dans le graphique explicite en connectant tous les noeuds de film en utilisant la relation :NEXT_WEIGHT dans l'ordre décroissant de poids, de sorte que les films construire une liste chaînée.

Votre requête ressemblerait à ceci:

MATCH p=(:Movie {name:'<name of movie with highest weight>'})-[:NEXT_WEIGHT*..1000]-() 
WHERE length(p)>skip_count AND length(p)<skip_count+limit 
WITH p 
ORDER BY length(p) 
WITH last(nodes(p)) as movie 
RETURN movie, toInt(movie.reviews_count) + toInt(movie.ratings_count) AS weight 

concernant la deuxième requête:

Vous devez utiliser un index pour accélérer la recherche de directeur. Malheureusement, les recherches d'index ne sont actuellement prises en charge que pour les recherches exactes. Donc, soit assurez-vous que la chaîne de recherche est correcte en termes de majuscules/minuscules ou stocker une version normalisée dans une autre propriété:

MATCH (d:Director) set d.lowerName = LOWER(d.name) 

Assurez-vous d'avoir un indice sur l'étiquette Director et la propriété LowerName:

CREATE INDEX ON :Director(lowerName) 

Et votre requête devrait ressembler à:

MATCH (director:Director)-[:Directed]->(movie) 
WHERE director.name = {directorName} 
RETURN movie, toInt(movie.ratings_count) * toInt(movie.reviews_count) *   toInt(movie.rating) AS total_weight 
ORDER BY total_weight DESC, movie.rating DESC 
LIMIT 10 
+0

Salut Stefan! Merci pour la réponse. Je pense que la première requête peut être structurée de cette façon pour la rendre plus efficace. MATCH p = (: Movie {nom: ''}) - [: NEXT_WEIGHT * limite] -() Renvoie des noeuds (p) (Comme je peux suivre le dernier film montré dans l'utilisateur session). Et pour la deuxième requête: existe-t-il un moyen d'utiliser le 'NEXT_WEIGHT' pour éviter d'utiliser' order by'? –

+1

Je suppose qu'un seul réalisateur n'a que <100 films où il a agi en tant que réalisateur. Ici, il devrait être assez rapide si vous vous assurez que trouver le noeud directeur est fait par une recherche d'index. –

+0

Oui, cela semble fonctionner dans ce cas. Mais est-il possible d'exécuter ceci en utilisant la relation 'NEXT_WEIGHT'. Alors qu'il peut être utilisé pour d'autres cas similaires aussi. –

Questions connexes