문서 보기역링크PDF로 내보내기맨 위로 이 문서는 읽기 전용입니다. 원본을 볼 수는 있지만 바꿀 수는 없습니다. 문제가 있다고 생각하면 관리자에게 문의하세요. # neomodel {{tag>neo4j neomodel ogm}} ## Connecting <code> from neomodel import config config.DATABASE_URL = 'bolt://neo4j:neo4j@localhost:7687' # default </code> ### change connection <code> from neomodel import db db.set_connection('bolt://neo4j:neo4j@localhost:7687') </code> ### 환경 변수 사용 <code shell> $ export NEO4J_USERNAME=neo4j $ export NEO4J_PASSWORD=neo4j $ export NEO4J_BOLT_URL="bolt://$NEO4J_USERNAME:$NEO4J_PASSWORD@localhost:7687" </code> <code python> import os from neomodel import config config.DATABASE_URL = os.environ["NEO4J_BOLT_URL"] </code> ## Node Entities and Relationships <code> 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') </code> [property-types](https://neomodel.readthedocs.io/en/latest/properties.html#property-types) ## Constrains and Indexes <code sh> $ neomodel_install_labels usage: neomodel_install_labels [-h] [--db bolt://neo4j:neo4j@localhost:7687] <someapp.models/app.py> [<someapp.models/app.py> ...] </code> ### Remove <code> $ neomodel_remove_labels --db bolt://neo4j:neo4j@localhost:7687 </code> ## Create, Update, Delete operations <code> jim = Person(name='Jim', age=3).save() # Create jim.age = 4 jim.save() # Update, (with validation) jim.delete() jim.refresh() # reload properties from the database jim.id # neo4j internal id </code> ## Retrieving nodes <code> # Return all nodes all_nodes = Person.nodes.all() # Returns Person by Person.name=='Jim' or raises neomodel.DoesNotExist if no match jim = Person.nodes.get(name='Jim') </code> <code> # 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) </code> ## Relationships <code> germany = Country(code='DE').save() jim.country.connect(germany) if jim.country.is_connected(germany): print("Jim's from Germany") for p in germany.inhabitant.all(): print(p.name) # Jim len(germany.inhabitant) # 1 # Find people called 'Jim' in germany # germany.inhabitant.search(name='Jim') result = germany.inhabitant.filter(name="Jim") result.all() # Find all the people called in germany except 'Jim' germany.inhabitant.exclude(name='Jim') # Remove Jim's country relationship with Germany jim.country.disconnect(germany) usa = Country(code='US').save() jim.country.connect(usa) jim.country.connect(germany) # Remove all of Jim's country relationships jim.country.disconnect_all() jim.country.connect(usa) # Replace Jim's country relationship with a new one jim.country.replace(germany) </code> <code> 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') </code> ### Cardinality <code> class Person(StructuredNode): car = RelationshipTo('Car', 'OWNS', cardinality=One) class Car(StructuredNode): owner = RelationshipFrom('Person', 'OWNS', cardinality=One) </code> The following cardinality constraints are available: - ZeroOrOne - One - ZeroOrMore (default) - OneOrMore ### Properties <code> class FriendRel(StructuredRel): since = DateTimeProperty( default=lambda: datetime.now(pytz.utc) ) 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" rel.save() </code> retrieve relationships <code> rel = jim.friends.relationship(bob) </code> ### Explicit Traversal <code> definition = dict(node_class=Person, direction=OUTGOING, relation_type=None, model=None) relations_traversal = Traversal(jim, Person.__label__, definition) all_jims_relations = relations_traversal.all() </code> ### Choices <code> class Person(StructuredNode): SEXES = {'F': 'Female', 'M': 'Male', 'O': 'Other'} sex = StringProperty(required=True, choices=SEXES) tim = Person(sex='M').save() tim.sex # M tim.get_sex_display() # 'Male' </code> ### Array Properties <code> class Person(StructuredNode): names = ArrayProperty(StringProperty(), required=True) bob = Person(names=['bob', 'rob', 'robert']).save() </code> ### Dates and times <code> 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 NEOMODEL_FORCE_TIMEZONE=1. </code> ### Complex lookups with Q objects <code> from neomodel import Q Q(name__startswith='Py') Lang.nodes.filter( Q(name__startswith='Py'), 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; </code> ### Has a relationship <code> Coffee.nodes.has(suppliers=True) </code> ### Filtering by relationship properties <code> coffee_brand = Coffee.nodes.get(name="BestCoffeeEver") for supplier in coffee_brand.suppliers.match(since_lt=january): print(supplier.name) </code> ### Ordering by property <code> # 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) </code> ## Cypher queries <code> 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] </code> ### Stand alone <code> # for standalone queries from neomodel import db results, meta = db.cypher_query(query, params) people = [Person.inflate(row[0]) for row in results] </code> ## Transactions ### Basic usage <code> from neomodel import db with db.transaction: Person(name='Bob').save() @db.transaction def update_user_name(uid, name): user = Person.nodes.filter(uid=uid)[0] user.name = name user.save() db.begin() try: new_user = Person(name=username, email=email).save() send_email(new_user) db.commit() except Exception as e: db.rollback() @task @db.transaction # comes after the task decorator def send_email(user): ... </code> ### Explicit Transactions <code> 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. </code> <code> With function decorators: @db.write_transaction def update_user_name(uid, name): user = Person.nodes.filter(uid=uid)[0] user.name = name user.save() @db.read_transaction def get_all_users(): return Person.nodes.all() @db.trasaction # Be default a WRITE transaction ... With explicit designation: db.begin("WRITE") ... db.begin("READ") ... db.begin() # By default a **WRITE** transaction </code> ## Hooks [Hooks](https://neomodel.readthedocs.io/en/latest/hooks.html) ## Ref - https://neomodel.readthedocs.io/en/latest/ open/neomodel.txt 마지막으로 수정됨: 2023/04/14 04:52저자 MORO