Search code examples
neo4jneo4j-apoc

How to add multiple labels using distinct using APOC for neo4j


I'm trying to add multiple labels to nodes using a cypher query, i would like to add 2 lables:

  1. title
  2. team

both exist on the node props:

CREATE (p:Person {id: 1, name: bob, title:developer, team: team1});

The following is working and adding the title as label:

match (n:Person)
with distinct n.title as title, collect(distinct n) as persons
call apoc.create.addLabels(persons, [apoc.text.upperCamelCase(title)]) yield node
return * 

Instead of running the same query again with the team attribute, I would like to use the same one with multiple districts values something like:

with distinct n.title as title and with distinct n.team as team collect(distinct n) as persons

which is not working, any idea if this is possible? or should I run 2 different queries for that?


Solution

  • I'm not sure that I understand the requirement for the distinct values, as apoc.create.addLabels will ignore labels that already exist on the target node.

    For example, given the following test data:

    MERGE (: Person { id: 1, name: 'Both Properties', title: 'some title', team: 'some team' })
    MERGE (: Person { id: 2, name: 'Only title', title: 'some title' })
    MERGE (: Person { id: 3, name: 'Only team', team: 'some team' })
    MERGE (: Person { id: 4, name: 'Neither team nor title' })
    MERGE (: Person { id: 5, name: 'Same team and title', title: 'admin', team: 'admin' })
    

    The following will build a list of labels to be created from the two properties, then set them:

    MATCH (p: Person)
    WITH p, [x in [p.title] + [p.team] WHERE x IS NOT NULL | apoc.text.upperCamelCase(x)] as desiredTitles
    CALL apoc.create.addLabels(p, desiredTitles) YIELD node
    RETURN p.name, labels(p)
    
    ╒════════════════════════╤═════════════════════════════════╕
    │"p.name"                │"labels(p)"                      │
    ╞════════════════════════╪═════════════════════════════════╡
    │"Both Properties"       │["Person","SomeTitle","SomeTeam"]│
    ├────────────────────────┼─────────────────────────────────┤
    │"Only title"            │["Person","SomeTitle"]           │
    ├────────────────────────┼─────────────────────────────────┤
    │"Only team"             │["Person","SomeTeam"]            │
    ├────────────────────────┼─────────────────────────────────┤
    │"Neither team nor title"│["Person"]                       │
    ├────────────────────────┼─────────────────────────────────┤
    │"Same team and title"   │["Person","Admin"]               │
    └────────────────────────┴─────────────────────────────────┘
    

    If either property is null then the list comprehension in the WITH statement will strip them out, and if they're the same then APOC ignores the duplicates automatically.