neo4j how to drop all constraints
Asked Answered
G

8

27

Is there a cypher command to drop all constraints?

I know I can drop specific constraints.

DROP CONSTRAINT ON (book:Book) ASSERT book.isbn IS UNIQUE

However I want to clear all constraints as part of teardown after testing. Can't find anything in the docs, but something like:

DROP CONSTRAINT *

Update: My testing setup.

Writing a tiny promise-based nodejs cypher client. I want to test defining unique indexes in application code.

Geer answered 12/3, 2014 at 16:10 Comment(5)
During testing, you want full setup&teardown, right? Rhere are a few approaches which could be helpful. Would you prefer: using a full server with the ability to drop an entire database with DROP GRAPH; a scriptable lightweight server which can host a graph at any directory you point to neo4jlite --serve ./test-graph.db; something else? Could you describe your particular testing setup?Yonder
@AndreasKollegger exactly! I tried DROP GRAPH but got a syntax error. In which Neo4J / CQL version is that supported?Geer
Sorry, I should've clarified that both approaches are theoretical, though realistic possibilities. With the usual balance between things-to-do and time-to-do-them, I'm trying to get a sense of where we should put more effort.Yonder
@Yonder DROP GRAPH would do it for me! right now I clear the database between test runs github.com/aj0strow/neo4j/blob/master/lib/neo4j.js#L57Geer
OK, I've extracted a feature request from this. Well, two. Please direct future comments to trello.com/c/OuGbPLt4Yonder
V
7

You can get a list of all indexes and constraints through GET requests to http://localhost:7474/db/data/schema/constraint/ and http://localhost:7474/db/data/schema/index. Here's how I do it in Ruby, maybe it'll give you an idea of how to do the same in Node.

c.after(:all) do
  conn = Faraday.new(url: "http://localhost:7474")
  response = conn.get('/db/data/schema/constraint/')
  constraints = JSON.parse(response.body)
  constraints.each do |constraint|
    Neo4j::Session.query("DROP CONSTRAINT ON (label:`#{constraint['label']}`) ASSERT label.#{constraint['property_keys'].first} IS UNIQUE")
  end 

  response = conn.get('/db/data/schema/index/')
  indexes = JSON.parse(response.body)
  indexes.each do |index|
    Neo4j::Session.query("DROP INDEX ON :`#{index['label']}`(#{index['property_keys'].first})")
  end
end
Vladikavkaz answered 27/9, 2014 at 18:40 Comment(1)
Yuck, why is a mix of http and session needed here?Breastpin
A
43

Note using APOC you can drop all indexes and constraints via CALL apoc.schema.assert({}, {}).

Amoreta answered 20/5, 2017 at 18:6 Comment(2)
Nice - that's amazing and quick!Summer
Nice library, when do they role this stuff into their core ;)Breastpin
V
7

You can get a list of all indexes and constraints through GET requests to http://localhost:7474/db/data/schema/constraint/ and http://localhost:7474/db/data/schema/index. Here's how I do it in Ruby, maybe it'll give you an idea of how to do the same in Node.

c.after(:all) do
  conn = Faraday.new(url: "http://localhost:7474")
  response = conn.get('/db/data/schema/constraint/')
  constraints = JSON.parse(response.body)
  constraints.each do |constraint|
    Neo4j::Session.query("DROP CONSTRAINT ON (label:`#{constraint['label']}`) ASSERT label.#{constraint['property_keys'].first} IS UNIQUE")
  end 

  response = conn.get('/db/data/schema/index/')
  indexes = JSON.parse(response.body)
  indexes.each do |index|
    Neo4j::Session.query("DROP INDEX ON :`#{index['label']}`(#{index['property_keys'].first})")
  end
end
Vladikavkaz answered 27/9, 2014 at 18:40 Comment(1)
Yuck, why is a mix of http and session needed here?Breastpin
B
7

Here is how I do this in Python:

    s = connection.get_session()

    # Drop constraints / indices
    for constraint in s.run("CALL db.constraints"):
        s.run("DROP " + constraint[0])

Feels a bit icky, I feel like constraints should be a better supported thing.

Breastpin answered 3/11, 2017 at 19:28 Comment(1)
Had to modify to "DROP CONSTRAINT". Thanks.Pinite
B
2

If you use node/javascript you can do something like:

const { records } = await cypher(`CALL db.constraints`)
await Promise.all(records.map(record => {
  cypher(`DROP CONSTRAINT ${record.get('name')}`);
}));
Bledsoe answered 14/4, 2020 at 16:39 Comment(1)
It's safer to drop constraints by name, e.g. DROP CONSTRAINT ${record.get('name')};, because if the attribute name requires the usage of "`" dropping by description won't work. Add this constraint to your database and check if your method works: CREATE CONSTRAINT ON (p:Person) ASSERT exists(p.`full name`);.Manufacture
D
2

I know the OP is asking about doing this programatically in testing, and this answer doesn't really satisfy that scenario. But if you're just looking to quickly delete all your constraints quickly without writing a program, you can generate a list of DROP CONSTRAINT commands using this query:

CALL db.constraints() YIELD name
RETURN "DROP CONSTRAINT " + name + ";";

Then you can quickly remove the pipes from the output and paste it back into cypher-shell to drop them all. It would probably be pretty easy to script that up with a shell script if it was something you wanted to do often.

Deliberative answered 26/10, 2021 at 3:24 Comment(0)
H
1

The only way to drop constraints is doing this on a per-constraint level. You can use e.g. :schema in the Neo4j browser to get a list of all constraints. I'd just write a short script for this.

Hofer answered 12/3, 2014 at 20:49 Comment(0)
C
0

Here is a helper for those using neo4jrb gem:

class MigrationHeper
  include Neo4j::Migrations::Helpers
  def drop_all
    execute("match (n) detach delete n;")
    execute("call db.constraints").each do |constraint|
      execute "drop " + constraint[:description]
    end
  end
end
Catchfly answered 6/8, 2018 at 21:34 Comment(0)
F
0

First of all, you have to create Neo4j class for connection:

class Neo4jConnection:
    
    def __init__(self, uri, user, pwd):
        
        self.__uri = uri
        self.__user = user
        self.__pwd = pwd
        self.__driver = None
        
        try:
            self.__driver = GraphDatabase.driver(self.__uri, auth=(self.__user, self.__pwd))
        except Exception as e:
            print("Failed to create the driver:", e)
        
    def close(self):
        
        if self.__driver is not None:
            self.__driver.close()
        
    def query(self, query, parameters=None, db=None):
        
        assert self.__driver is not None, "Driver not initialized!"
        session = None
        response = None
        
        try: 
            session = self.__driver.session(database=db) if db is not None else self.__driver.session() 
            response = list(session.run(query, parameters))
        except Exception as e:
            print("Query failed:", e)
        finally: 
            if session is not None:
                session.close()
        return response

After that create a connection:

uri = 'uri'
pwd = 'pwd'
user= 'user'

conn = Neo4jConnection(uri=uri, user=user , pwd=pwd)

And, you can run the below to delete all constraints:

## drop all constraints
const = conn.query("CALL db.constraints")

for c in const:
    conn.query(f"DROP CONSTRAINT {c['name']}")
Fridafriday answered 29/9, 2021 at 21:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.