2015-04-24 19 views
5

Czy istnieje sposób użycia UNWIND dla potencjalnie pustych kolekcji (na przykład OPCJONALNY UNWIND g)?Cypher: Użyj UNWIND z potencjalnie pustą kolekcją

Na przykład w załączonym zapytaniu okazuje się, że kolekcja (elementy) jest czasami pusta (trzeci blok), ale wyniki innych kolekcji są nadal aktualne.

Tutaj chcę zgnieść niektóre liczby dla pod-wykresu i zwrócić liczbę różnych typów węzłów (grupa, użytkownicy, lokalizacja, element, grupy elementów). Grupy produktów można uzyskać tylko za pomocą pozycji. Ponieważ wiele elementów jest dołączonych do wielu użytkowników, byłoby to bardzo powolne, jeśli dołączę grupy elementów bezpośrednio do drugiego bloku bez agregowania w pierwszej kolejności.

MATCH(group: Group {id: "12345"}) 
OPTIONAL MATCH(group) - [: IS_PARENT * 0..] - > (subgroup: Group) 

WITH collect(distinct subgroup) as groups 
UNWIND groups as group 
    OPTIONAL MATCH(u: User) - [: BELONGS_TO] - > (group) 
    OPTIONAL MATCH(u) --(i: Item) 
    OPTIONAL MATCH(u) --(l: Location) 
WITH groups, collect(distinct u) as users, collect(distinct i) as items, collect(distinct l) as locations 
UNWIND items as i 
    OPTIONAL MATCH(i) --(ig: FunctionalArea) 
RETURN length(groups), length(users), length(items), length(locations), count(distinct ig) 

Znalazłem obejście, ale nie jestem z tego zadowolony. Kiedy wstawię sztuczny węzeł do kolekcji elementów, mogę go odpakować za każdym razem bez utraty wyników.

MATCH(group: Group {id: "12345"}) 
OPTIONAL MATCH(group) - [: IS_PARENT * 0..] - > (subgroup: Group) 

WITH collect(distinct subgroup) as groups 
UNWIND groups as group 
    OPTIONAL MATCH(u: User) - [: BELONGS_TO] - > (group) 
    OPTIONAL MATCH(u) --(i: Item) 
    OPTIONAL MATCH(u) --(l: Location) 
WITH groups, collect(distinct u) as users, collect(distinct i) as items, collect(distinct l) as locations 

>> 
MATCH(ig:ItemGroup) 
WITH groups, users, ([head(collect(ig))] + items) as items, locations 
<< 
UNWIND items as i 
    OPTIONAL MATCH(i) --(ig: FunctionalArea) 
RETURN length(groups), length(users), length(items), length(locations), count(distinct ig) 

Rozważam napisanie dwóch osobnych zapytań, ale to doprowadziłoby do złożonej logiki klienta.

Wszelkie pomysły i wskazówki są bardzo doceniane.

Dzięki!

+1

miałem tę samą zagadkę. Poszedłem także do korzenia węzła 'manekina'. Na pewno brakowało mu elegancji, ale wydawało się, że działa dobrze. Chciałbym usłyszeć o innych potencjalnych rozwiązaniach, szczególnie tych bardziej eleganckich. –

Odpowiedz

1

Proponuję, aby zamiast zrezygnować z tak wielu próśb, zreorganizować zapytanie.

Jego szybkie refactored jedną, ale jej tylko sugestia;) sprawdzić to pls:

MATCH(group: Group {id: "12345"})-[:IS_PARENT*0..]->(subgroup: Group) 
OPTIONAL MATCH(u: User)-[: BELONGS_TO]->(subgroup) 
OPTIONAL MATCH(u) -- (l: Location) 

WITH COLLECT(DISTINCT subgroup) AS g, COLLECT(DISTINCT u) AS uc, 
    count(distinct subgroup) as groups, 
    count(distinct u) as users, 
    count(distinct l) as locations 

UNWIND uc as u 

OPTIONAL MATCH(u) --(i: Item) 
OPTIONAL MATCH(i) --(ig: FunctionalArea) 

RETURN groups, users, count(DISTINCT i) AS items, locations, count(distinct ig) 

Podgrupa będą zbierać autonomicznych grup korzeniowych, jak również, bc * 0 ... Więc pierwszy opcjonalny mecz nie jest już potrzebny.

Zrobiłem tak szybko, jak to możliwe. Tylko użytkownicy potrzebni na drugim poziomie do zbierania danych przedmiotów. Enjoy :)

7

Można użyć:

UNWIND (CASE items WHEN [] then [null] else items end) as item