Skip to content

Updated examples and docs #929

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 36 additions & 79 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,99 +47,56 @@ Quick Example

.. code-block:: python

from neo4j import GraphDatabase
from neo4j import GraphDatabase, RoutingControl

driver = GraphDatabase.driver("neo4j://localhost:7687",
auth=("neo4j", "password"))

def add_friend(tx, name, friend_name):
tx.run("MERGE (a:Person {name: $name}) "
"MERGE (a)-[:KNOWS]->(friend:Person {name: $friend_name})",
name=name, friend_name=friend_name)
URI = "neo4j://localhost:7687"
AUTH = ("neo4j", "password")

def print_friends(tx, name):
query = ("MATCH (a:Person)-[:KNOWS]->(friend) WHERE a.name = $name "
"RETURN friend.name ORDER BY friend.name")
for record in tx.run(query, name=name):
print(record["friend.name"])

with driver.session(database="neo4j") as session:
session.execute_write(add_friend, "Arthur", "Guinevere")
session.execute_write(add_friend, "Arthur", "Lancelot")
session.execute_write(add_friend, "Arthur", "Merlin")
session.execute_read(print_friends, "Arthur")

driver.close()


Connection Settings Breaking Change (4.x)
=========================================

+ The driver’s default configuration for encrypted is now false
(meaning that driver will only attempt plain text connections by default).

+ Connections to encrypted services (such as Neo4j Aura) should now explicitly
be set to encrypted.

+ When encryption is explicitly enabled, the default trust mode is to trust the
CAs that are trusted by operating system and use hostname verification.

+ This means that encrypted connections to servers holding self-signed
certificates will now fail on certificate verification by default.

+ Using the new ``neo4j+ssc`` scheme will allow to connect to servers holding self-signed certificates and not use hostname verification.

+ The ``neo4j://`` scheme replaces ``bolt+routing://`` and can be used for both clustered and single-instance configurations with Neo4j 4.0.



See, https://neo4j.com/docs/migration-guide/4.0/upgrade-driver/#upgrade-driver-breakingchanges

def add_friend(driver, name, friend_name):
driver.execute_query(
"MERGE (a:Person {name: $name}) "
"MERGE (friend:Person {name: $friend_name}) "
"MERGE (a)-[:KNOWS]->(friend)",
name=name, friend_name=friend_name, database_="neo4j",
)

See, https://neo4j.com/docs/driver-manual/current/client-applications/#driver-connection-uris for changes in default security settings between 3.x and 4.x

def print_friends(driver, name):
records, _, _ = driver.execute_query(
"MATCH (a:Person)-[:KNOWS]->(friend) WHERE a.name = $name "
"RETURN friend.name ORDER BY friend.name",
name=name, database_="neo4j", routing_=RoutingControl.READ,
)
for record in records:
print(record["friend.name"])

Connecting with Python Driver 4.x to Neo4j 3.5 (EOL)
----------------------------------------------------

Using the Python Driver 4.x and connecting to Neo4j 3.5 with default connection settings for Neo4j 3.5.

.. code-block:: python

# the preferred form

driver = GraphDatabase.driver("neo4j+ssc://localhost:7687", auth=("neo4j", "password"))

# is equivalent to

driver = GraphDatabase.driver("neo4j://localhost:7687", auth=("neo4j", "password"), encrypted=True, trust=False)


Connecting with Python Driver 1.7 (EOL) to Neo4j 4.x
----------------------------------------------------

Using the Python Driver 1.7 and connecting to Neo4j 4.x with default connection settings for Neo4j 4.x.

.. code-block:: python

driver = GraphDatabase.driver("neo4j://localhost:7687", auth=("neo4j", "password"), encrypted=False)
with GraphDatabase.driver(URI, auth=AUTH) as driver:
add_friend(driver, "Arthur", "Guinevere")
add_friend(driver, "Arthur", "Lancelot")
add_friend(driver, "Arthur", "Merlin")
print_friends(driver, "Arthur")


Other Information
=================
Further Information
===================

* `The Neo4j Operations Manual`_
* `The Neo4j Drivers Manual`_
* `Python Driver API Documentation`_
* `Neo4j Cypher Refcard`_
* `Example Project`_
* `The Neo4j Operations Manual`_ (docs on how to run a Neo4j server)
* `The Neo4j Python Driver Manual`_ (good introduction to this driver)
* `Python Driver API Documentation`_ (full API documentation for this driver)
* `Neo4j Cypher Cheat Sheet`_ (summary of Cypher syntax - Neo4j's graph query language)
* `Example Project`_ (small web application using this driver)
* `GraphAcademy`_ (interactive, free online trainings for Neo4j)
* `Driver Wiki`_ (includes change logs)
* `Neo4j 4.0 Migration Guide`_
* `Neo4j Migration Guide`_

.. _`The Neo4j Operations Manual`: https://neo4j.com/docs/operations-manual/current/
.. _`The Neo4j Drivers Manual`: https://neo4j.com/docs/driver-manual/current/
.. _`The Neo4j Python Driver Manual`: https://neo4j.com/docs/python-manual/current/
.. _`Python Driver API Documentation`: https://neo4j.com/docs/api/python-driver/current/
.. _`Neo4j Cypher Refcard`: https://neo4j.com/docs/cypher-refcard/current/
.. _`Neo4j Cypher Cheat Sheet`: https://neo4j.com/docs/cypher-cheat-sheet/
.. _`Example Project`: https://github.com/neo4j-examples/movies-python-bolt
.. _`GraphAcademy`: https://graphacademy.neo4j.com/categories/python/
.. _`Driver Wiki`: https://github.com/neo4j/neo4j-python-driver/wiki
.. _`Neo4j 4.0 Migration Guide`: https://neo4j.com/docs/migration-guide/4.0/
.. _`Neo4j Migration Guide`: https://neo4j.com/docs/migration-guide/current/
2 changes: 1 addition & 1 deletion docs/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1030,7 +1030,7 @@ See :class:`.BookmarkManager` for more information.
``auth``
--------
Optional :class:`neo4j.Auth` or ``(user, password)``-tuple. Use this overwrite the
authentication information for the session.
authentication information for the session (user-switching).
This requires the server to support re-authentication on the protocol level. You can
check this by calling :meth:`.Driver.supports_session_auth` / :meth:`.AsyncDriver.supports_session_auth`.

Expand Down
169 changes: 85 additions & 84 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ To install the latest pre-release, use:
python -m pip install --pre neo4j


.. TODO: 7.0 - remove this note

.. note::

``neo4j-driver`` is the old name for this package. It is now deprecated and
and will receive no further updates starting with 6.0.0. Make sure to
install ``neo4j`` as shown above.

.. note::

It is always recommended to install python packages for user space in a virtual environment.
Expand Down Expand Up @@ -100,60 +108,40 @@ To deactivate the current active virtual environment, use:
Quick Example
*************

Creating nodes and relationships.

.. code-block:: python

from neo4j import GraphDatabase
from neo4j import GraphDatabase, RoutingControl


URI = "neo4j://localhost:7687"
AUTH = ("neo4j", "password")


def create_person(tx, name):
tx.run("CREATE (a:Person {name: $name})", name=name)
def add_friend(driver, name, friend_name):
driver.execute_query(
"MERGE (a:Person {name: $name}) "
"MERGE (friend:Person {name: $friend_name}) "
"MERGE (a)-[:KNOWS]->(friend)",
name=name, friend_name=friend_name, database_="neo4j",
)


def create_friend_of(tx, name, friend):
tx.run("MATCH (a:Person) WHERE a.name = $name "
"CREATE (a)-[:KNOWS]->(:Person {name: $friend})",
name=name, friend=friend)
def print_friends(driver, name):
records, _, _ = driver.execute_query(
"MATCH (a:Person)-[:KNOWS]->(friend) WHERE a.name = $name "
"RETURN friend.name ORDER BY friend.name",
name=name, database_="neo4j", routing_=RoutingControl.READ,
)
for record in records:
print(record["friend.name"])


with GraphDatabase.driver(URI, auth=AUTH) as driver:
with driver.session() as session:
session.execute_write(create_person, "Alice")
session.execute_write(create_friend_of, "Alice", "Bob")
session.execute_write(create_friend_of, "Alice", "Carl")

add_friend(driver, "Arthur", "Guinevere")
add_friend(driver, "Arthur", "Lancelot")
add_friend(driver, "Arthur", "Merlin")
print_friends(driver, "Arthur")

Finding nodes.

.. code-block:: python

from neo4j import GraphDatabase


URI = "neo4j://localhost:7687"
AUTH = ("neo4j", "password")


def get_friends_of(tx, name):
friends = []
result = tx.run("MATCH (a:Person)-[:KNOWS]->(f) "
"WHERE a.name = $name "
"RETURN f.name AS friend", name=name)
for record in result:
friends.append(record["friend"])
return friends


with GraphDatabase.driver(URI, auth=AUTH) as driver:
with driver.session() as session:
friends = session.execute_read(get_friends_of, "Alice")
for friend in friends:
print(friend)


*******************
Expand All @@ -163,99 +151,112 @@ Example Application
.. code-block:: python

import logging
from neo4j import GraphDatabase
from neo4j.exceptions import ServiceUnavailable

from neo4j import GraphDatabase, RoutingControl
from neo4j.exceptions import DriverError, Neo4jError


class App:

def __init__(self, uri, user, password):
def __init__(self, uri, user, password, database=None):
self.driver = GraphDatabase.driver(uri, auth=(user, password))
self.database = database

def close(self):
# Don't forget to close the driver connection when you are finished with it
# Don't forget to close the driver connection when you are finished
# with it
self.driver.close()

def create_friendship(self, person1_name, person2_name):
with self.driver.session() as session:
# Write transactions allow the driver to handle retries and transient errors
result = session.execute_write(
self._create_and_return_friendship, person1_name, person2_name)
for record in result:
print("Created friendship between: {p1}, {p2}".format(
p1=record['p1'], p2=record['p2']))
# Write transactions allow the driver to handle retries and
# transient errors
result = self._create_and_return_friendship(
person1_name, person2_name
)
print("Created friendship between: "
f"{result['p1']}, {result['p2']}")

@staticmethod
def _create_and_return_friendship(tx, person1_name, person2_name):
def _create_and_return_friendship(self, person1_name, person2_name):

# To learn more about the Cypher syntax,
# see https://neo4j.com/docs/cypher-manual/current/

# The Reference Card is also a good resource for keywords,
# see https://neo4j.com/docs/cypher-refcard/current/
# The Cheat Sheet is also a good resource for keywords,
# see https://neo4j.com/docs/cypher-cheat-sheet/

query = (
"CREATE (p1:Person { name: $person1_name }) "
"CREATE (p2:Person { name: $person2_name }) "
"CREATE (p1)-[:KNOWS]->(p2) "
"RETURN p1, p2"
"RETURN p1.name, p2.name"
)
result = tx.run(query, person1_name=person1_name, person2_name=person2_name)
try:
return [{"p1": record["p1"]["name"], "p2": record["p2"]["name"]}
for record in result]
record = self.driver.execute_query(
query, person1_name=person1_name, person2_name=person2_name,
database_=self.database,
result_transformer_=lambda r: r.single(strict=True)
)
return {"p1": record["p1.name"], "p2": record["p2.name"]}
# Capture any errors along with the query and data for traceability
except ServiceUnavailable as exception:
logging.error("{query} raised an error: \n {exception}".format(
query=query, exception=exception))
except (DriverError, Neo4jError) as exception:
logging.error("%s raised an error: \n%s", query, exception)
raise

def find_person(self, person_name):
with self.driver.session() as session:
result = session.execute_read(self._find_and_return_person, person_name)
for record in result:
print("Found person: {record}".format(record=record))
names = self._find_and_return_person(person_name)
for name in names:
print(f"Found person: {name}")

@staticmethod
def _find_and_return_person(tx, person_name):
def _find_and_return_person(self, person_name):
query = (
"MATCH (p:Person) "
"WHERE p.name = $person_name "
"RETURN p.name AS name"
)
result = tx.run(query, person_name=person_name)
return [record["name"] for record in result]
names = self.driver.execute_query(
query, person_name=person_name,
database_=self.database, routing_=RoutingControl.READ,
result_transformer_=lambda r: r.value("name")
)
return names

if __name__ == "__main__":
# See https://neo4j.com/developer/aura-connect-driver/ for Aura specific connection URL.
# For Aura specific connection URI,
# see https://neo4j.com/developer/aura-connect-driver/ .
scheme = "neo4j" # Connecting to Aura, use the "neo4j+s" URI scheme
host_name = "example.com"
port = 7687
url = f"{scheme}://{host_name}:{port}"
uri = f"{scheme}://{host_name}:{port}"
user = "<Username for Neo4j database>"
password = "<Password for Neo4j database>"
app = App(url, user, password)
database = "neo4j"
app = App(uri, user, password, database)
try:
app.create_friendship("Alice", "David")
app.find_person("Alice")
finally:
app.close()


*****************
Other Information
*****************
*******************
Further Information
*******************

* `Neo4j Documentation`_
* `The Neo4j Drivers Manual`_
* `Cypher Cheat Sheet`_
* `Example Project`_
* `The Neo4j Operations Manual`_ (docs on how to run a Neo4j server)
* `The Neo4j Python Driver Manual`_ (good introduction to this driver)
* `Python Driver API Documentation`_ (full API documentation for this driver)
* `Neo4j Cypher Cheat Sheet`_ (summary of Cypher syntax - Neo4j's graph query language)
* `Example Project`_ (small web application using this driver)
* `GraphAcademy`_ (interactive, free online trainings for Neo4j)
* `Driver Wiki`_ (includes change logs)
* `Neo4j Aura`_
* `Neo4j Migration Guide`_

.. _`Neo4j Documentation`: https://neo4j.com/docs/
.. _`The Neo4j Drivers Manual`: https://neo4j.com/docs/driver-manual/current/
.. _`Cypher Cheat Sheet`: https://neo4j.com/docs/cypher-cheat-sheet/current/
.. _`The Neo4j Operations Manual`: https://neo4j.com/docs/operations-manual/current/
.. _`The Neo4j Python Driver Manual`: https://neo4j.com/docs/python-manual/current/
.. _`Python Driver API Documentation`: https://neo4j.com/docs/api/python-driver/current/
.. _`Neo4j Cypher Cheat Sheet`: https://neo4j.com/docs/cypher-cheat-sheet/
.. _`Example Project`: https://github.com/neo4j-examples/movies-python-bolt
.. _`GraphAcademy`: https://graphacademy.neo4j.com/categories/python/
.. _`Driver Wiki`: https://github.com/neo4j/neo4j-python-driver/wiki
.. _`Neo4j Aura`: https://neo4j.com/neo4j-aura/
.. _`Neo4j Migration Guide`: https://neo4j.com/docs/migration-guide/current/
Loading