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.

AJcodez
  • 31,780
  • 20
  • 84
  • 118
  • 1
    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? – akollegger Mar 13 '14 at 00:25
  • @AndreasKollegger exactly! I tried `DROP GRAPH` but got a syntax error. In which Neo4J / CQL version is that supported? – AJcodez Mar 13 '14 at 20:49
  • 1
    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. – akollegger Mar 14 '14 at 22:03
  • @akollegger `DROP GRAPH` would do it for me! right now I clear the database between test runs https://github.com/aj0strow/neo4j/blob/master/lib/neo4j.js#L57 – AJcodez Mar 15 '14 at 19:09
  • 3
    OK, I've extracted a feature request from this. Well, two. Please direct future comments to https://trello.com/c/OuGbPLt4 – akollegger Mar 17 '14 at 17:05

8 Answers8

43

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

John
  • 783
  • 6
  • 12
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
subvertallchris
  • 5,282
  • 2
  • 25
  • 43
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.

meawoppl
  • 2,714
  • 1
  • 23
  • 30
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')}`);
}));
Matt Brandt
  • 581
  • 1
  • 4
  • 20
  • 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\`);`. – Telmo Trooper Jul 05 '20 at 23:54
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.

Graham Lea
  • 5,797
  • 3
  • 40
  • 55
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.

Stefan Armbruster
  • 39,465
  • 6
  • 87
  • 97
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
Sam
  • 4,000
  • 20
  • 27
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']}")
iamvarol
  • 11
  • 1