# expandConfig - Exclude nodes with specific connections

**URL:** <https://community.neo4j.com/t/expandconfig-exclude-nodes-with-specific-connections/41106>\
**Category:** Procedures & APOC\
**Created:** [July 9, 2021, 12:38am UTC](https://community.neo4j.com/t/expandconfig-exclude-nodes-with-specific-connections/41106 "2021-07-09T00:38:11Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![mdausmann.cmri](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/mdausmann.cmri/32/15320_2.png) [@mdausmann.cmri](https://community.neo4j.com/u/mdausmann.cmri)\
**Post date:** [July 9, 2021, 12:38am UTC](https://community.neo4j.com/t/expandconfig-exclude-nodes-with-specific-connections/41106/1 "2021-07-09T00:38:11Z")

</div>

Hi folks.

**TLDR** : Is it possible with APOC to include a node in labelFilter but also exclude instances of that node type that also connect to another type of node?

I have a schema that describes the relationships between projects, operations and materials. I want to write a query that finds finalised materials that 'belong to' a particular project. This seems simple but is complicated by the fact that sometimes intermediate materials are 're-used' by secondary projects to produce more outputs and I want to exclude these from the material results of the initial project.

A Simplified example of my problem can be created with the following:

```auto
create (p1:PROJECT:EXAMPLE{name:'p1'})
with p1
create (p2:PROJECT:EXAMPLE{name:'p2'})
with p1, p2
create (p1)<-[:BELONGS_TO]-(o1:OPERATION:EXAMPLE{name:'o1'})-[:OUT]->(m1:MATERIAL:EXAMPLE{name:'m1'})-[:IN]->(o2:OPERATION:EXAMPLE{name:'o2'})-[:OUT]->(m2:MATERIAL:EXAMPLE{name:'m2'})-[:IN]->(o3:OPERATION:EXAMPLE{name:'o3'})-[:OUT]->(m3:MATERIAL:USEFUL:EXAMPLE{name:'m3'})
create (p2)<-[:BELONGS_TO]-(o4:OPERATION:EXAMPLE{name:'o4'})<-[:IN]-(m2)
create (o4)-[:OUT]->(m4:MATERIAL:USEFUL:EXAMPLE{name:'m4'})

```

...Looks like this...

 ![Screen Shot 2021-07-09 at 10.05.40 am](https://us1.discourse-cdn.com/flex021/uploads/neo4jcommunity/original/3X/2/d/2dcf58f2741ec8c59f78e0feb102bc41ff5e458a.png)

Note that Operations produce materials and also belong to projects. Note also that Material 'm2' has been _re-used_ by Project 'p2' to produce material 'm4'

My first attempt at the query just uses apoc expandConfig...

```auto
match (p:PROJECT{name:'p1'})<-[:BELONGS_TO]-(op:OPERATION)
call apoc.path.expandConfig(op, {relationshipFilter:'IN>|OUT>', 
labelFilter:'OPERATION|MATERIAL|>USEFUL',
uniqueness: 'NODE_GLOBAL'
}) yield path
with last(nodes(path)) as usefulMaterials
return usefulMaterials.name as name

```

This does return 'm3' but also incorrectly returns the material that results from project 'p2's re-use 'm4'

My Second attempt uses a blacklistNodes approach to exclude a pre-matched set of nodes that belong to projects. .....

```auto
match (o:OPERATION)-[:BELONGS_TO]->(p:PROJECT)
with collect(o) AS projectOps
match (p:PROJECT{name:'p1'})<-[:BELONGS_TO]-(op:OPERATION)
call apoc.path.expandConfig(op, {relationshipFilter:'IN>|OUT>', 
labelFilter:'OPERATION|MATERIAL|>USEFUL',
uniqueness: 'NODE_GLOBAL',
blacklistNodes: projectOps
}) yield path
with last(nodes(path)) as usefulMaterials
return usefulMaterials.name as name

```

This approach correctly returns only "m3' for 'p1' and if I swap to 'p2', it correctly returns 'm4'

So it works, but seems very inefficient. As my DB grows larger, the set of projectOps nodes is going to get very large.

Is it possible with APOC to include the OPERATION node in labelFilter but also exclude OPERATION nodes that also connect to a project i.e. exclude

```auto
(o:OPERATION)-[:BELONGS_TO]->(p:PROJECT)

```

---

<div class="post-metadata">

**Author:** ![mdausmann.cmri](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/mdausmann.cmri/32/15320_2.png) [@mdausmann.cmri](https://community.neo4j.com/u/mdausmann.cmri)\
**Post date:** [July 12, 2021, 6:20am UTC](https://community.neo4j.com/t/expandconfig-exclude-nodes-with-specific-connections/41106/3 "2021-07-12T06:20:12Z")

</div>

I have had another crack at this. It's not elegant but I can use 2 APOC traversals as shown below. This should not blow out as the db gets larger.. Still would like a more concise solution though

```auto
//First traversal to find child ops that belong to other projects
match (p:PROJECT{name:'p1'})<-[:BELONGS_TO]-(op:OPERATION)
call apoc.path.expandConfig(op, {relationshipFilter:'IN>|OUT>', 
	labelFilter:'>OPERATION|MATERIAL',
	uniqueness: 'NODE_GLOBAL'
	}) yield path
with last(nodes(path)) as o
match(o)-[:BELONGS_TO]->(pi:PROJECT)
with collect(o) AS projectOps

//Second traversal avoiding 'owned' ops
match (p:PROJECT{name:'p1'})<-[:BELONGS_TO]-(op:OPERATION)
call apoc.path.expandConfig(op, {relationshipFilter:'IN>|OUT>', 
	labelFilter:'OPERATION|MATERIAL|>USEFUL',
	uniqueness: 'NODE_GLOBAL',
	blacklistNodes: projectOps
	}) yield path
with last(nodes(path)) as usefulMaterials
return usefulMaterials.name as name

```

---

<div class="post-metadata">

**Author:** ![Cobra](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/cobra/32/35243_2.png) [@Cobra](https://community.neo4j.com/u/Cobra)\
**Post date:** [July 12, 2021, 6:42am UTC](https://community.neo4j.com/t/expandconfig-exclude-nodes-with-specific-connections/41106/4 "2021-07-12T06:42:02Z")

</div>

Hello @mdausmann.cmri 🙂

Neo4j can manage nodes with multiple labels so that you can add a node label to the nodes you want to exclude.

Regards,  
Cobra

---

<div class="post-metadata">

**Author:** ![mdausmann.cmri](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/mdausmann.cmri/32/15320_2.png) [@mdausmann.cmri](https://community.neo4j.com/u/mdausmann.cmri)\
**Post date:** [July 13, 2021, 12:19am UTC](https://community.neo4j.com/t/expandconfig-exclude-nodes-with-specific-connections/41106/5 "2021-07-13T00:19:03Z")

</div>

Hi @Cobra

Thanks for taking the time to look at my question.

I agree, if the project nodes had an additional tag e.g :-

```auto
(o4:OPERATION:OWNED:EXAMPLE{name:'o4'})

```

then I could use this syntax in my labelFilter

```auto
labelFilter:'-OWNED|OPERATION|MATERIAL|>USEFUL',

```

But I kind of think that the relationship between the :OPERATION and :PROJECT nodes already represents the 'owned' concept in my schema and that adding a label would be redundant and require extra work to keep up to date. I was really hoping to solve this without adding additional labels or attributes.

Regards,  
Michael

---

<div class="post-metadata">

**Author:** ![mdausmann.cmri](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/mdausmann.cmri/32/15320_2.png) [@mdausmann.cmri](https://community.neo4j.com/u/mdausmann.cmri)\
**Post date:** [July 15, 2021, 2:03am UTC](https://community.neo4j.com/t/expandconfig-exclude-nodes-with-specific-connections/41106/6 "2021-07-15T02:03:55Z")

</div>

I have reviewed this with a colleague and we have decided that this solution is not _too_ horrible.
