2014-12-09 11 views
7

Supponiamo che io ho un nodo con una collezione in una proprietà, diconoCypher: analogo di `sort -u` per unire 2 collezioni?

START x = node(17) SET x.c = [ 4, 6, 2, 3, 7, 9, 11 ]; 

e da qualche parte (cioè da file .csv) ottengo un altro insieme di valori, dico

c1 = [ 11, 4, 5, 8, 1, 9 ] 

sto trattando le mie collezioni come set, l'ordine degli elementi non ha importanza. Quello di cui ho bisogno è di unire x.c con c1 con l'operazione come magic in modo che il risultato x.c conterrà solo elementi distinti da entrambi. La seguente idea viene in mente (ancora sottoposti a verifica):

LOAD CSV FROM "file:///tmp/additives.csv" as row 
START x=node(TOINT(row[0])) 
MATCH c1 = [ elem IN SPLIT(row[1], ':') | TOINT(elem) ] 
SET 
x.c = [ newxc IN x.c + c1 WHERE (newx IN x.c AND newx IN c1) ]; 

Questo non funziona, darà un incrocio, ma non un insieme di elementi distinti. Altro RTFM offre un'altra idea: utilizzare REDUCE()? ma come?

Come estendere Cypher con una nuova funzione incorporata UNIQUE() che accetta la raccolta e la restituzione della raccolta, i duplicati della forma pulita?

UPD. Sembra che il filtro() è qualcosa di vicino, ma ancora una volta intersezione :(

x.c = FILTER(newxc IN x.c + c1 WHERE (newx IN x.c AND newx IN c1)) 

WBR, Andrii

risposta

4

Che ne dite di qualcosa di simile ...

with [1,2,3] as a1 
, [3,4,5] as a2 
with a1 + a2 as all 
unwind all as a 
return collect(distinct a) as unique 

Aggiungere due collezioni e restituire il raccolta di elementi distinti

dec 15, 2014 - ecco un aggiornamento alla mia risposta ...

ho iniziato con un nodo nel database Neo4j ...

//create a node in the DB with a collection of values on it 
create (n:Node {name:"Node 01",values:[4,6,2,3,7,9,11]}) 
return n 

ho creato un file CSV di esempio con due colonne ...

Name,Coll 
"Node 01","11,4,5,8,1,9" 

ho creato una dichiarazione LOAD CSV .. .

LOAD CSV 
WITH HEADERS FROM "file:///c:/Users/db/projects/coll-merge/load_csv_file.csv" as row 

// find the matching node 
MATCH (x:Node) 
WHERE x.name = row.Name 

// merge the collections 
WITH x.values + split(row.Coll,',') AS combo, x 

// process the individual values 
UNWIND combo AS value 

// use toInt as the values from the csv come in as string 
// may be a better way around this but i am a little short on time 
WITH toInt(value) AS value, x 

// might as well sort 'em so they are all purdy 
ORDER BY value 
WITH collect(distinct value) AS values, x 
SET x.values = values 
+2

GMM grazie per il puntatore direzione giusta, dovrei [leggere la documentazione meglio: c'è "Creare una raccolta distinta" capitolo laggiù] (http://neo4j.com/docs/stable/query-unwind.html#unwind-create-a-distinct-collection) :) – stesin

+0

a volte dovrei leggere anche questa –

+1

buona risposta, questo è più efficiente di ridurre penso –

2

Si potrebbe usare ridurre in questo modo:

with [1,2,3] as a, [3,4,5] as b 
return reduce(r = [], x in a + b | case when x in r then r else r + [x] end) 
1

Poiché Neo4j 3.0, con APOC Procedures, è possibile risolvere facilmente questo problema con apoc.coll.union(). In 3.1+ è una funzione, e può essere utilizzato in questo modo:

... 
WITH apoc.coll.union(list1, list2) as unionedList 
...