from neomodel import config
config.DATABASE_URL = 'bolt://neo4j:neo4j@localhost:7687'  # default

from neomodel import db

$ export NEO4J_USERNAME=neo4j
$ export NEO4J_PASSWORD=neo4j
$ export NEO4J_BOLT_URL="bolt://$NEO4J_USERNAME:$NEO4J_PASSWORD@localhost:7687"

import os
from neomodel import config
config.DATABASE_URL = os.environ["NEO4J_BOLT_URL"]

from neomodel import (config, StructuredNode, StringProperty, IntegerProperty,
    UniqueIdProperty, RelationshipTo)

config.DATABASE_URL = 'bolt://neo4j:password@localhost:7687'

class Country(StructuredNode):
    code = StringProperty(unique_index=True, required=True)

class Person(StructuredNode):
    uid = UniqueIdProperty()
    name = StringProperty(unique_index=True)
    age = IntegerProperty(index=True, default=0)

    # traverse outgoing IS_FROM relations, inflate to Country objects
    country = RelationshipTo(Country, 'IS_FROM')


$ neomodel_install_labels
usage: neomodel_install_labels [-h] [--db bolt://neo4j:neo4j@localhost:7687] <someapp.models/> [<someapp.models/> ...]

$ neomodel_remove_labels --db bolt://neo4j:neo4j@localhost:7687

jim = Person(name='Jim', age=3).save() # Create
jim.age = 4 # Update, (with validation)
jim.refresh() # reload properties from the database # neo4j internal id

# Return all nodes
all_nodes = Person.nodes.all()

# Returns Person by'Jim' or raises neomodel.DoesNotExist if no match
jim = Person.nodes.get(name='Jim')

# Will return None unless "bob" exists
someone = Person.nodes.get_or_none(name='bob')

# Will return the first Person node with the name bob. This raises neomodel.DoesNotExist if there's no match.
someone = Person.nodes.first(name='bob')

# Will return the first Person node with the name bob or None if there's no match
someone = Person.nodes.first_or_none(name='bob')

# Return set of nodes
people = Person.nodes.filter(age__gt=3)

germany = Country(code='DE').save()

    print("Jim's from Germany")

for p in germany.inhabitant.all():
    print( # Jim

len(germany.inhabitant) # 1

# Find people called 'Jim' in germany
result = germany.inhabitant.filter(name="Jim")

# Find all the people called in germany except 'Jim'

# Remove Jim's country relationship with Germany

usa = Country(code='US').save()

# Remove all of Jim's country relationships
# Replace Jim's country relationship with a new one

class Person(StructuredNode):
    friends = Relationship('Person', 'FRIEND')

When defining relationships, you may refer to classes in other modules. This avoids cyclic imports:

class Garage(StructuredNode):
    cars = RelationshipTo('transport.models.Car', 'CAR')
    vans = RelationshipTo('.models.Van', 'VAN')

class Person(StructuredNode):
    car = RelationshipTo('Car', 'OWNS', cardinality=One)

class Car(StructuredNode):
    owner = RelationshipFrom('Person', 'OWNS', cardinality=One)

The following cardinality constraints are available:

  • ZeroOrOne
  • One
  • ZeroOrMore (default)
  • OneOrMore

class FriendRel(StructuredRel):
    since = DateTimeProperty(
    met = StringProperty()

class Person(StructuredNode):
    name = StringProperty()
    friends = RelationshipTo('Person', 'FRIEND', model=FriendRel)

rel = jim.friends.connect(bob)
rel.since # datetime object

rel = jim.friends.connect(bob,
                          {'since': yesterday, 'met': 'Paris'})

print(rel.start_node().name) # jim
print(rel.end_node().name) # bob

rel.met = "Amsterdam"

retrieve relationships

rel = jim.friends.relationship(bob)

definition = dict(node_class=Person, direction=OUTGOING,
                  relation_type=None, model=None)
relations_traversal = Traversal(jim, Person.__label__,
all_jims_relations = relations_traversal.all()

class Person(StructuredNode):
    SEXES = {'F': 'Female', 'M': 'Male', 'O': 'Other'}
    sex = StringProperty(required=True, choices=SEXES)

tim = Person(sex='M').save() # M
tim.get_sex_display() # 'Male'

class Person(StructuredNode):
    names = ArrayProperty(StringProperty(), required=True)

bob = Person(names=['bob', 'rob', 'robert']).save()

created = DateTimeFormatProperty(format="%Y-%m-%d %H:%M:%S")

created = DateTimeProperty(default_now=True)

# Enforcing a specific timezone is done by setting the config variable 

from neomodel import Q

    Q(year=2005) | Q(year=2006)

# This roughly translates to the following Cypher query:

MATCH (lang:Lang) WHERE name STARTS WITH 'Py'
    AND (year = 2005 OR year = 2006)
    return lang;


coffee_brand = Coffee.nodes.get(name="BestCoffeeEver")

for supplier in coffee_brand.suppliers.match(since_lt=january):

# Ascending sort
for coffee in Coffee.nodes.order_by('price'):
    print(coffee, coffee.price)

# Descending sort
for supplier in Supplier.nodes.order_by('-delivery_cost'):
    print(supplier, supplier.delivery_cost)

class Person(StructuredNode):
    def friends(self):
        results, columns = self.cypher("MATCH (a) WHERE id(a)={self} MATCH (a)-[:FRIEND]->(b) RETURN b")
        return [self.inflate(row[0]) for row in results]

# for standalone queries
from neomodel import db
results, meta = db.cypher_query(query, params)
people = [Person.inflate(row[0]) for row in results]

from neomodel import db

with db.transaction:
def update_user_name(uid, name):
    user = Person.nodes.filter(uid=uid)[0] = name
    new_user = Person(name=username, email=email).save()
except Exception as e:
@db.transaction  # comes after the task decorator
def send_email(user):

with db.read_transaction:

with db.write_transaction:

with db.transaction:
    # This designates the transaction as WRITE even if
    # the the enclosed block of code will not modify the
    # database state.

With function decorators:

def update_user_name(uid, name):
    user = Person.nodes.filter(uid=uid)[0] = name

def get_all_users():
    return Person.nodes.all()

@db.trasaction # Be default a WRITE transaction
With explicit designation:

db.begin() # By default a **WRITE** transaction

  • open/neomodel.txt
  • 마지막으로 수정됨: 2023/04/14 04:52
  • 저자 MORO