GraphRefactoring { @Procedure(mode = Mode.WRITE) @Description("apoc.refactor.normalizeAsBoolean(entity, propertyKey, true_values, false_values) normalize/convert a property to be boolean") public void normalizeAsBoolean( @Name("entity") Object entity, @Name("propertyKey") String propertyKey, @Name("true_values") List<Object> trueValues, @Name("false_values") List<Object> falseValues) { if (entity instanceof Entity) { Entity pc = (Entity) entity; Object value = pc.getProperty(propertyKey, null); if (value != null) { boolean isTrue = trueValues.contains(value); boolean isFalse = falseValues.contains(value); if (isTrue && !isFalse) { pc.setProperty(propertyKey, true); } if (!isTrue && isFalse) { pc.setProperty(propertyKey, false); } if (!isTrue && !isFalse) { pc.removeProperty(propertyKey); } } } }  @Procedure(mode = Mode.WRITE) @Description("apoc.refactor.extractNode([rel1,rel2,...], [labels],'OUT','IN') extract node from relationships") Stream<NodeRefactorResult> extractNode(@Name("relationships") Object rels, @Name("labels") List<String> labels, @Name("outType") String outType, @Name("inType") String inType); @Procedure(mode = Mode.WRITE) @Description("apoc.refactor.collapseNode([node1,node2],'TYPE') collapse node to relationship, node with one rel becomes self-relationship") Stream<RelationshipRefactorResult> collapseNode(@Name("nodes") Object nodes, @Name("type") String type); @Procedure(mode = Mode.WRITE) @Description("apoc.refactor.cloneNodes([node1,node2,...]) clone nodes with their labels and properties") Stream<NodeRefactorResult> cloneNodes(@Name("nodes") List<Node> nodes,
                                                 @Name(value = "withRelationships", defaultValue = "false") boolean withRelationships,
                                                 @Name(value = "skipProperties", defaultValue = "[]") List<String> skipProperties); @Procedure(mode = Mode.WRITE) @Deprecated @Description("apoc.refactor.cloneNodesWithRelationships([node1,node2,...]) clone nodes with their labels, properties and relationships") Stream<NodeRefactorResult> cloneNodesWithRelationships(@Name("nodes") List<Node> nodes); @Procedure(mode = Mode.WRITE) @Description("apoc.refactor.cloneSubgraphFromPaths([path1, path2, ...], {standinNodes:[], skipProperties:[]}) YIELD input, output, error | " + "from the subgraph formed from the given paths, clone nodes with their labels and properties (optionally skipping any properties in the skipProperties list via the config map), and clone the relationships (will exist between cloned nodes only). " + "Relationships can be optionally redirected according to standinNodes node pairings (this is a list of list-pairs of nodes), so given a node in the original subgraph (first of the pair), " + "an existing node (second of the pair) can act as a standin for it within the cloned subgraph. Cloned relationships will be redirected to the standin.") Stream<NodeRefactorResult> cloneSubgraphFromPaths(@Name("paths") List<Path> paths,
                                                             @Name(value="config", defaultValue = "{}") Map<String, Object> config); @Procedure(mode = Mode.WRITE) @Description("apoc.refactor.cloneSubgraph([node1,node2,...], [rel1,rel2,...]:[], {standinNodes:[], skipProperties:[]}) YIELD input, output, error | " + "clone nodes with their labels and properties (optionally skipping any properties in the skipProperties list via the config map), and clone the given relationships (will exist between cloned nodes only). " + "If no relationships are provided, all relationships between the given nodes will be cloned. " + "Relationships can be optionally redirected according to standinNodes node pairings (this is a list of list-pairs of nodes), so given a node in the original subgraph (first of the pair), " + "an existing node (second of the pair) can act as a standin for it within the cloned subgraph. Cloned relationships will be redirected to the standin.") Stream<NodeRefactorResult> cloneSubgraph(@Name("nodes") List<Node> nodes,
                                                    @Name(value="rels", defaultValue = "[]") List<Relationship> rels,
                                                    @Name(value="config", defaultValue = "{}") Map<String, Object> config); @Procedure(mode = Mode.WRITE,eager = true) @Description("apoc.refactor.mergeNodes([node1,node2],[{properties:'overwrite' or 'discard' or 'combine'}]) merge nodes onto first in list") Stream<NodeResult> mergeNodes(@Name("nodes") List<Node> nodes, @Name(value = "config", defaultValue = "{}") Map<String, Object> config); @Procedure(mode = Mode.WRITE) @Description("apoc.refactor.mergeRelationships([rel1,rel2]) merge relationships onto first in list") Stream<RelationshipResult> mergeRelationships(@Name("rels") List<Relationship> relationships, @Name(value = "config", defaultValue = "{}") Map<String, Object> config); @Procedure(mode = Mode.WRITE) @Description("apoc.refactor.setType(rel, 'NEW-TYPE') change relationship-type") Stream<RelationshipRefactorResult> setType(@Name("relationship") Relationship rel, @Name("newType") String newType); @Procedure(mode = Mode.WRITE,eager = true) @Description("apoc.refactor.to(rel, endNode) redirect relationship to use new end-node") Stream<RelationshipRefactorResult> to(@Name("relationship") Relationship rel, @Name("newNode") Node newNode); @Procedure(mode = Mode.WRITE,eager = true) @Description("apoc.refactor.invert(rel) inverts relationship direction") Stream<RelationshipRefactorResult> invert(@Name("relationship") Relationship rel); @Procedure(mode = Mode.WRITE, eager = true) @Description("apoc.refactor.from(rel, startNode) redirect relationship to use new start-node") Stream<RelationshipRefactorResult> from(@Name("relationship") Relationship rel, @Name("newNode") Node newNode); @Procedure(mode = Mode.WRITE) @Description("apoc.refactor.normalizeAsBoolean(entity, propertyKey, true_values, false_values) normalize/convert a property to be boolean") void normalizeAsBoolean(
            @Name("entity") Object entity,
            @Name("propertyKey") String propertyKey,
            @Name("true_values") List<Object> trueValues,
            @Name("false_values") List<Object> falseValues); @Procedure(mode = Mode.WRITE) @Description("apoc.refactor.categorize(sourceKey, type, outgoing, label, targetKey, copiedKeys, batchSize) turn each unique propertyKey into a category node and connect to it") void categorize(
            @Name("sourceKey") String sourceKey,
            @Name("type") String relationshipType,
            @Name("outgoing") Boolean outgoing,
            @Name("label") String label,
            @Name("targetKey") String targetKey,
            @Name("copiedKeys") List<String> copiedKeys,
            @Name("batchSize") long batchSize
    ); @Context
    public Transaction tx; @Context
    public GraphDatabaseService db; @Context
    public Log log; @Context
    public Pools pools; }
@Test public void testNormalizeAsBoolean() throws Exception { db.executeTransactionally("CREATE ({prop: 'Y', id:1}),({prop: 'Yes', id: 2}),({prop: 'NO', id: 3}),({prop: 'X', id: 4})"); testResult( db, "MATCH (n) CALL apoc.refactor.normalizeAsBoolean(n,'prop',['Y','Yes'],['NO']) WITH n ORDER BY n.id RETURN n.prop AS prop", (r) -> { List<Boolean> result = new ArrayList<>(); while (r.hasNext()) result.add((Boolean) r.next().get("prop")); assertThat(result, equalTo(Arrays.asList(true, true, false, null))); } ); }