Neo4j: Match multiple labels (2 or more)

后端 未结 6 1093
轮回少年
轮回少年 2020-12-07 22:14

I would like to do a search, and I would like to start traversing from 2 labels (OR condition). For example, I need to find out all the nodes which have labels either \'Male

相关标签:
6条回答
  • 2020-12-07 22:44

    If you want to filter node by multiple labels with OR or IN condition, use this code:

    MATCH (n)
    WHERE labels(n) in [['Male'],['Female']]
    AND n.name =~ '.ail.'
    RETURN n
    
    0 讨论(0)
  • 2020-12-07 22:51

    As for v3.5, we can do:

    MATCH (n) WHERE (n:User OR n:Admin) AND n.name CONTAINS "ail" RETURN n
    

    and get:

    ╒══════════════════╕
    │"n"               │
    ╞══════════════════╡
    │{"name":"Abigail"}│
    ├──────────────────┤
    │{"name":"Bailee"} │
    └──────────────────┘
    
    0 讨论(0)
  • 2020-12-07 23:01
    MATCH n WHERE n:Label1 OR n:Label2
    

    ... will result in an AllNodesScan this is a bad Idea!

    maybe a better solution:

    OPTIONAL MATCH (n1:Label1)
    WITH collect(distinct n1) as c1
    
    OPTIONAL MATCH (n2:Label2) 
    WITH collect(distinct n2) + c1 as c2
    
    OPTIONAL MATCH (n3:Label3) 
    WITH collect(distinct n3) + c2 as c3
    
    UNWIND c3 as nodes
    RETURN count(nodes),labels(nodes) 
    
    0 讨论(0)
  • With Neo4j 3.4.7 the query planner does a UNION and then a DISTINCT of 2 NodeByLabelScans when you hand it a WHERE query with 2 OR'ed label filters. Trying the sandbox Offshore Leaks Database with EXPLAIN MATCH (o) WHERE o:Officer OR o:Entity RETURN o yields this planning:

    0 讨论(0)
  • 2020-12-07 23:05

    Documentation for v3.0 says this:

    One can also describe a node that has multiple labels:

    (a:User:Admin)-->(b)

    Source: https://neo4j.com/docs/developer-manual/current/cypher/#_labels

    0 讨论(0)
  • 2020-12-07 23:09

    You can put this condition in the WHERE clause:

    MATCH (n)
    WHERE n:Male OR n:Female
    RETURN n
    

    EDIT

    As @tbaum points out this performs an AllNodesScan. I wrote the answer when labels were fairly new and expected the query planner to eventually implement it with a NodeByLabelScan for each label, as it does for the single label case

    MATCH (n)
    WHERE n:Male
    RETURN n
    

    I still think this is a reasonable expression of the query and that it is reasonable to expect the query planner to implement it with label scans, but as of Neo4j 2.2.3 the query is still implemented with an AllNodesScan and a label filter. Here is therefore a more verbose alternative. Since the label disjunction signifies a set union and this union can be expressed in different ways, we can express it in a way that the query planner implements without scanning all nodes, and instead starts with a NodeByLabelScan per label.

    MATCH (n:Male)
    WHERE n.name =~ '.ail.'
    RETURN n
    UNION MATCH (n:Female)
    WHERE n.name =~ '.ail.'
    RETURN n
    

    This means expressing the query once for each label and joining them with an explicit UNION. This is not unreasonable, at least for smaller number of labels, but it's not clear to me why the query planners shouldn't be able to infer the same implementation from the simpler query so I have opened a github issue here.

    0 讨论(0)
提交回复
热议问题