Domanda

Ho una domanda come questa:

MATCH left, right 
WHERE (ID(right) IN [1, 2, 3] AND ID(left) IN [4, 5, 6]) 
WITH left, right 
  LIMIT 1 
RETURN left, right 
UNION MATCH left, right 
WHERE (ID(right) IN [1, 2, 3] AND ID(left) IN [4, 5, 6]) 
WITH left, right 
  SKIP 4 LIMIT 1 
RETURN left, right 
UNION MATCH left, right 
WHERE (ID(right) IN [1, 2, 3] AND ID(left) IN [4, 5, 6]) 
WITH left, right 
  SKIP 8 LIMIT 1 
RETURN left, right
CREATE UNIQUE left-[rel:FRIEND]->right 
RETURN rel;

In generale, sto semplicemente creando un set di dati in modo da poterlo utilizzare in seguito nell'istruzione CREATE UNIQUE.
Ovviamente non funziona: l'analizzatore di query dice che posso utilizzare la clausola RETURN solo una volta.La mia domanda è: come comporre un set di dati in questo caso?Ho provato ad assegnare un alias e ad usarlo in CREATE UNIQUE - non riesco neanche a farlo funzionare.Che cosa sto facendo di sbagliato?Questo scenario è possibile?

È stato utile?

Soluzione

Potrei fraintendere quello che stai cercando, ma ecco cosa mi viene in mente quando guardo la tua domanda.

Per cominciare ecco un adattamento della tua query che utilizza SKIP E LIMIT senza RETURN O UNION.

MATCH left, right
WHERE ID(left) IN [1,2,3] AND ID(right) IN [4,5,6]
WITH left, right 
    LIMIT 1
CREATE UNIQUE left-[rel:FRIEND]->right
WITH [rel] as rels  //If you want to return the relationship later you can put it in a collection and bring it WITH
MATCH left, right
WHERE ID(left) IN [1,2,3] AND ID(right) IN [4,5,6]
WITH left, right, rels 
    SKIP 4 LIMIT 1
CREATE UNIQUE left-[rel:FRIEND]->right
WITH rels + [rel] as rels
MATCH left, right
WHERE ID(left) IN [1,2,3] AND ID(right) IN [4,5,6]
WITH left, right, rels 
    SKIP 8 LIMIT 1
CREATE UNIQUE left-[rel:FRIEND]->right
WITH rels + [rel] as rels
RETURN LENGTH(rels), rels  // You can return the relationships here but SKIP/LIMIT does its job also if you don't return anything

Ma questa domanda è un po’ selvaggia.In realtà sono tre query, di cui due sono state artificialmente inserite come sottoquery della prima.Corrisponde nuovamente agli stessi nodi in ciascuna sottoquery e in realtà non si ottiene nulla eseguendo le query in questo modo anziché separatamente (in realtà è più lento, perché in ogni sottoquery si abbinano anche i nodi che sai che non utilizzerai) .

Quindi il mio primo suggerimento è usare START invece di MATCH...WHERE quando si ottengono i nodi tramite ID.Allo stato attuale, la query associa ogni nodo del database come "sinistra", quindi ogni nodo del database come "destra", quindi filtra tutti i nodi associati a "sinistra" che non soddisfano la condizione in IL WHERE clausola, e poi lo stesso per "giusto".Poiché questa parte della query viene ripetuta tre volte, tutti i nodi del database vengono associati per un totale di sei volte.È costoso creare tre relazioni.Se usi START puoi unire subito i nodi che desideri.Questo non risponde realmente alla tua domanda, ma sarà più veloce e la query sarà più chiara.Quindi, usa START per ottenere i nodi in base al loro ID interno.

START left = node(1,2,3), right = node(4,5,6)

La seconda cosa a cui penso è la differenza tra nodi e "percorsi" o "elementi di risultato" quando si abbinano i modelli.Quando leghi tre nodi a "sinistra" e altri tre nodi a "destra", non hai tre elementi risultato, ma nove.Per ogni nodo legato a "sinistra" si ottengono tre risultati, perché ci sono tre possibili "destre" con cui combinarlo.Se volessi mettere in relazione ogni "sinistra" con ogni "destra", bene.Ma penso che quello che stai cercando siano gli elementi risultato (1),(4), (2),(5), (3),(6), e sebbene sembri conveniente associare i tre nodi "sinistri" e i tre nodi "destri" in un'unica query con raccolte di ID nodo, devi eseguire tutto il filtraggio per eliminare le 6 corrispondenze indesiderate.La query diventa complessa e macchinosa ed è in realtà più lenta rispetto all'esecuzione delle query separatamente.Un altro modo per dirlo è dire quello (1)-[:FRIEND]->(4) è un pattern distinto, non (rilevante) connesso agli altri pattern che stai creando.Sarebbe diverso se volessi creare (1)-[:FRIEND]->(2)<-[:FRIEND]-(3), allora vorresti gestire questi tre nodi insieme.Forse stai solo esplorando usi marginali del cypher, ma ho pensato che dovrei sottolinearlo.A proposito, usando SKIP E LIMIT in questo modo è un po' stonato, non sono realmente destinati alla corrispondenza e al filtraggio dei pattern.È anche imprevedibile, a meno che non lo usi anche tu ORDER BY, poiché non vi è alcuna garanzia che i risultati siano in un determinato ordine.Non sai quale elemento di risultato viene trasmesso.Ad ogni modo, in questo caso, penso che sarebbe meglio associare i nodi e creare la relazione in tre query separate.

START left = node(1), right = node(4)
CREATE UNIQUE left-[rel:FRIEND]->right
RETURN rel

START left = node(2), right = node(5)
CREATE UNIQUE left-[rel:FRIEND]->right
RETURN rel

START left = node(3), right = node(6)
CREATE UNIQUE left-[rel:FRIEND]->right
RETURN rel

Dal momento che sai già che vuoi quelle tre paia e non, diciamo, (1),(4),(1),(5),(1),(6) avrebbe senso eseguire una query solo per quelle coppie e il modo più semplice è eseguire una query separatamente.

Ma in terzo luogo, poiché le tre query sono strutturalmente identiche, differendo solo per il valore della proprietà (se id è una proprietà) è possibile semplificare la query generalizzando o anonimizzando ciò che le distingue, ovveroutilizzare i parametri.

START left = node({leftId}), right = node({rightId})
CREATE UNIQUE left-[rel:FRIEND]->right
RETURN rel

parameters: {leftId:1, rightId:4}, {leftId:2, rightId:5}, {leftId:3, rightId:6}

Poiché la struttura è identica, cypher può memorizzare nella cache il piano di esecuzione.Ciò garantisce buone prestazioni e la query è ordinata, manutenibile e può essere facilmente estesa se in seguito si desidera eseguire la stessa operazione su altre coppie di nodi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top