Accessing Neo4j Node property using cypher in python - python

I'm trying to get the node property in python, which I earlier created with name property as Marco
student = db.labels.create("Student")
u1 = db.nodes.create(name="Marco")
student.add(u1)
When I queried on neo4j UI using query
MATCH (n:Student) where n.name="gaurav" RETURN n.name
It returned me property of the node.
But how do I get same property in python, presently I'm using below script to query the DB, but I dont know how to get property name from this query sequence.
result = db.query("MATCH (a:Student) WHERE a.name = {} RETURN a ", {"name":
"Marco"}, returns=(client.Node))

As explained in https://marcobonzanini.com/2015/04/06/getting-started-with-neo4j-and-python/ you can do this :
results = db.query("MATCH (a:Student) WHERE a.name = {} RETURN a ", {"name":
"Marco"}, returns=(client.Node))
for r in results:
print("(%s)" % (r[0]["name"]))
Hope this helps,
Tom

Related

Python Flask SqlAlchemy Add Database Model Name dynamically in For Loop

I am not that familiar with Python and SQLAlchemy so please be patient :)
I need to capture if, within a FORM that holds multiple ICONS(files), one or more ICONS have been changed when editing the record.
To see which ICONS have been changed I created an Object holding the changes with "Database Model Name" as the "Key" and its "Value"
{'icon': <FileStorage: 'fire.png' ('image/png')>}
key = used as database model name
value = file.filename
now when I try the get the data within a for loop and add this data to the Database model, nothing happens and it looks like I am not really accessing variable "k" in the loop.
for k, v in notequalat.items():
responseteamdata.k = v.filename
My question is, how can I combine the Database model class "responseteamdata" and the variable "k" so that I can add the changes to the database model dynamically.
here is the full code:
if not notequalat:
try:
responseteamdata.title = title
responseteamdata.abbreviation = abbreviation
responseteamdata.isfireteam = booleanisfireteam
responseteamdata.iconposition = newlatlng
db.session.commit()
except IntegrityError:
db.session.rollback()
db.session.close()
res = make_response(jsonify("message ", "Error Updating the Team"), 500)
return res
else:
responseteamdata.title = title
responseteamdata.abbreviation = abbreviation
responseteamdata.isfireteam = booleanisfireteam
responseteamdata.iconposition = newlatlng
for k, v in notequalat.items():
responseteamdata.k = v.filename
db.session.commit()
dbevent = "updated"
db.session.close()
To be able to dynamically assign the Table Column Name the following command has been working for me:
setattr(DB-Object, ColumnName, Value)
which means in my case:
setattr(responseteamdata, k, v.filename)

How do I use a python variable value to name a new node created in neo4j

I have the following line of code
tx.run(CREATE n) using the bolt library for neo4j to python.
I will be receiving a user input which I store in a variable, and I wish to name the node according to that. How should I approach this? Thanks
Another instance could be this. I get a CQL syntax error with this
if(tx.run("MATCH(n:Player{name: playername_})" "RETURN n")):
tx.run("CREATE (playername_:Player)")
tx.run("MATCH(username_:User)(playername_:Player)" "CREATE (playername_)-[r:IN_TEAM]->(username_)")
else:
tx.run("MATCH(username_:User)(playername_:Player)" "CREATE (playername_)-[r:IN_TEAM]->(username_)")
The tx.run("CREATE (playername_:Player)") line throws up the following error
neo4j.exceptions.CypherSyntaxError: {code: Neo.ClientError.Statement.SyntaxError} {message: Variable `playername_` not defined (line 1, column 22 (offset: 21)) "MATCH(n:Player{name: playername_})RETURN n"
I believe this could help you:
playername = 'Joe'
username = 'Martin'
tx.run("CREATE (n:Player) SET n.playername = $playernamePar", playernamePar=playername)
tx.run("CREATE (n:User) SET n.username = $usernamePar", usernamePar=username)
tx.run("MATCH (p:Player),(u:User)
WHERE p.playername = $playernamePar
AND u.username = $usernamePar
CREATE (p)-[:inTeam]->(u)",
playernamePar=playername, usernamePar=username)

How can I get all the hops in a path of unknown length with neo4j-python?

MATCH (u:User {name: $user}), (target:Group {name: $group}), p=shortestPath((u)-[*]->(target)) RETURN p
When I run the above query in the Neo4j web UI, a fell graph of the resulting paths is displayed.
However, when I run the same query with the neo4j-python driver, only a Path objects with limited information are returned
<Path start=479557 end=404582 size=1>
How can I use Cypher and python to get complete path details, including all nodes and the relationships that connect them?
Depends on how you want to return data, but you can try something like this
MATCH (u:User {name: $user}), (target:Group {name: $group}),
p=shortestPath((u)-[*]->(target)) RETURN nodes(p),relationships(p)
Thanks for the help everyone! For reference, here's my complete example that converts paths to human-readable strings for console or email output.
def find_paths_from_standard_user_to_domain_admins(standard_user, domain_admins_group):
"""Returns a list of paths that a standard user could take to get domain admin credentials"""
results = []
query = "MATCH (u:User {name:{user}}), (target:Group {name: {group}})," \
"p=allShortestPaths((u)-[*]->(target)) RETURN p"
with driver.session() as session:
with session.begin_transaction() as tx:
for record in tx.run(query, user=standard_user, group=domain_admins_group):
relationships = record["p"].relationships
nodes = record["p"].nodes
path = ""
for i in (range(len(relationships))):
path += "{0}-[{1}]->".format(nodes[i]["name"], relationships[i].type)
path += nodes[-1]["name"]
results.append(path)
return results
This is a query for a graph generated by the Bloodhound project, which builds graphs of Active Directory structures. It's extremely useful for domain admins, system architects, network defenders, and pentesters.
https://neo4j.com/docs/api/python-driver/4.0/api.html#path
https://neo4j.com/docs/api/python-driver/4.0/api.html#relationship
from neo4j import (
Path,
Relationship,
)
...
result = session.run("MATCH (u:User {name: $user}), (target:Group {name: $group}), p=shortestPath((u)-[*]->(target)) RETURN p", user="example", name="example").single()
record = result.single()
session.close()
path = record["p"]
assert isinstance(path, Path)
for relationship in path:
assert isinstance(relationship, Relationship)

py2neo (1.6) how to get an existing node by node property without CypherQuery

I'm using py2neo (version 1.6). I want to get an existing node by its property from the graph and then use it to create a relationship.
My solution:
graph = neo4j.GraphDatabaseService("http://...")
query = neo4j.CypherQuery(graph,"MATCH (n:NodeType) where n.property = 'property' return n")
r = query.execute()
if len(r.data)==0:
raise Exception("node does not exist")
node = r.data[0]['n']
newNode = batch.create(node(name="APropertyOfNewNode"))
batch.add_labels(newNode, "LableOfNewNode")
relation = rel(node, "relationshipName", newNode)
batch.create(relation)
batch.submit()
batch.clear()
Is there an high level way to get an existing node by its property without using CypherQuery and writing plain cypher?
You can use GraphDatabaseService.find:
from py2neo import neo4j
graph = neo4j.GraphDatabaseService('http://localhost:7474/db/data/')
movies = graph.find('Movie', 'title', 'The Matrix')
But graph.find returns a generator object.
movies
# <generator object find at 0x10b64acd0>
So you can only iterate through it once.
for movie in movies:
print type(movie)
print movie['tagline']
# <class 'py2neo.neo4j.Node'>
# Welcome to the Real World

Union and Intersect in Django

class Tag(models.Model):
name = models.CharField(maxlength=100)
class Blog(models.Model):
name = models.CharField(maxlength=100)
tags = models.ManyToManyField(Tag)
Simple models just to ask my question.
I wonder how can i query blogs using tags in two different ways.
Blog entries that are tagged with "tag1" or "tag2":
Blog.objects.filter(tags_in=[1,2]).distinct()
Blog objects that are tagged with "tag1" and "tag2" : ?
Blog objects that are tagged with exactly "tag1" and "tag2" and nothing else : ??
Tag and Blog is just used for an example.
You could use Q objects for #1:
# Blogs who have either hockey or django tags.
from django.db.models import Q
Blog.objects.filter(
Q(tags__name__iexact='hockey') | Q(tags__name__iexact='django')
)
Unions and intersections, I believe, are a bit outside the scope of the Django ORM, but its possible to to these. The following examples are from a Django application called called django-tagging that provides the functionality. Line 346 of models.py:
For part two, you're looking for a union of two queries, basically
def get_union_by_model(self, queryset_or_model, tags):
"""
Create a ``QuerySet`` containing instances of the specified
model associated with *any* of the given list of tags.
"""
tags = get_tag_list(tags)
tag_count = len(tags)
queryset, model = get_queryset_and_model(queryset_or_model)
if not tag_count:
return model._default_manager.none()
model_table = qn(model._meta.db_table)
# This query selects the ids of all objects which have any of
# the given tags.
query = """
SELECT %(model_pk)s
FROM %(model)s, %(tagged_item)s
WHERE %(tagged_item)s.content_type_id = %(content_type_id)s
AND %(tagged_item)s.tag_id IN (%(tag_id_placeholders)s)
AND %(model_pk)s = %(tagged_item)s.object_id
GROUP BY %(model_pk)s""" % {
'model_pk': '%s.%s' % (model_table, qn(model._meta.pk.column)),
'model': model_table,
'tagged_item': qn(self.model._meta.db_table),
'content_type_id': ContentType.objects.get_for_model(model).pk,
'tag_id_placeholders': ','.join(['%s'] * tag_count),
}
cursor = connection.cursor()
cursor.execute(query, [tag.pk for tag in tags])
object_ids = [row[0] for row in cursor.fetchall()]
if len(object_ids) > 0:
return queryset.filter(pk__in=object_ids)
else:
return model._default_manager.none()
For part #3 I believe you're looking for an intersection. See line 307 of models.py
def get_intersection_by_model(self, queryset_or_model, tags):
"""
Create a ``QuerySet`` containing instances of the specified
model associated with *all* of the given list of tags.
"""
tags = get_tag_list(tags)
tag_count = len(tags)
queryset, model = get_queryset_and_model(queryset_or_model)
if not tag_count:
return model._default_manager.none()
model_table = qn(model._meta.db_table)
# This query selects the ids of all objects which have all the
# given tags.
query = """
SELECT %(model_pk)s
FROM %(model)s, %(tagged_item)s
WHERE %(tagged_item)s.content_type_id = %(content_type_id)s
AND %(tagged_item)s.tag_id IN (%(tag_id_placeholders)s)
AND %(model_pk)s = %(tagged_item)s.object_id
GROUP BY %(model_pk)s
HAVING COUNT(%(model_pk)s) = %(tag_count)s""" % {
'model_pk': '%s.%s' % (model_table, qn(model._meta.pk.column)),
'model': model_table,
'tagged_item': qn(self.model._meta.db_table),
'content_type_id': ContentType.objects.get_for_model(model).pk,
'tag_id_placeholders': ','.join(['%s'] * tag_count),
'tag_count': tag_count,
}
cursor = connection.cursor()
cursor.execute(query, [tag.pk for tag in tags])
object_ids = [row[0] for row in cursor.fetchall()]
if len(object_ids) > 0:
return queryset.filter(pk__in=object_ids)
else:
return model._default_manager.none()
I've tested these out with Django 1.0:
The "or" queries:
Blog.objects.filter(tags__name__in=['tag1', 'tag2']).distinct()
or you could use the Q class:
Blog.objects.filter(Q(tags__name='tag1') | Q(tags__name='tag2')).distinct()
The "and" query:
Blog.objects.filter(tags__name='tag1').filter(tags__name='tag2')
I'm not sure about the third one, you'll probably need to drop to SQL to do it.
Please don't reinvent the wheel and use django-tagging application which was made exactly for your use case. It can do all queries you describe, and much more.
If you need to add custom fields to your Tag model, you can also take a look at my branch of django-tagging.
This will do the trick for you
Blog.objects.filter(tags__name__in=['tag1', 'tag2']).annotate(tag_matches=models.Count(tags)).filter(tag_matches=2)

Categories