How to construct a graph in SQlModel? - graph

I am trying to use SQLModel to create a graph Node that would keep it's connections/links in it so that it can be traversed and stored in the database.
I started of upgrading the Node class defined in other SQL answer, which works fine but is designed for One-to-Many link.
I have added "links" field:
class Node(SQLModel, table=True):
...
id: Optional[int] = Field(default=None, primary_key=True)
...
links: list['Node'] = Relationship(back_populates='links', link_model=NodeLink)
...and a "NodeLink" model for Many-to-Many to work:
class NodeLink(SQLModel, table=True):
this_id: Optional[int] = Field(
default=None, foreign_key="node.id", primary_key=True
)
other_id: Optional[int] = Field(
default=None, foreign_key="node.id", primary_key=True
)
...but this does not work. Can someone nudge me to correct me to the right track?
NB: Finally, my plan is to add weights to the nodes and making links updated automatically for both connected nodes when one gets linked.

Related

ValidationError when using pydantic Field

I run these codes by defining two classes, Blackboard and Table, based on BaseModel. The I defined another class which takes two attributes: bloackboard, defined to be a Blackboard; tables, defined to be a list of Table class objects.
from typing import List
from pydantic import BaseModel, Field
class Blackboard(BaseModel):
size = 4000
color: str = Field(..., alias='yanse',
description='the color of the blackboard, you can choose green or black.')
class Table(BaseModel):
position: str
class ClassRoom(BaseModel):
blackboard: Blackboard
tables: List[Table]
m = ClassRoom(
blackboard={'color': 'green'},
tables=[{'position': 'first row, left 1'}, {'position': 'first row, left 2'}]
)
I got an error :
File "pydantic\main.py", line 342, in pydantic.main.BaseModel.__init__
pydantic.error_wrappers.ValidationError: 1 validation error for ClassRoom
blackboard -> yanse
field required (type=value_error.missing)
I want to know how could I correctly use Field class.
Thanks
I expect to have no error.
You are using an alias for the color field in your schema and filling your data with python dictionaries.
in this case, you should replace:
blackboard={'color': 'green'}
with:
blackboard={'yanse': 'green'}
The color field is used when you have a python schema object, not in dictionaries.
In case you wanted to populate your Blackboard model using color, you can activate allow_population_by_field_name option in the Blackboard config options as follow:
class Blackboard(BaseModel):
size = 4000
color: str = Field(..., alias='yanse',
description='the color of the blackboard,
you can choose green or black.')
class Config:
allow_population_by_field_name = True

Can you insert relationship ID to other relationship when creating nodes in Neo4J?

I have one CQL syntax, and I don't understand how to add relationship id to another relationship within a single query. This is the sample that might give clearer description about what I need
CREATE
(a:IP_ADDRESS {name: "224.36.71.118"}),
(b:TARGET {honeypot: "cowrie", target_post: "2222", target_protocol: "tcp", analyzer_id: "VM1"}),
(c:Unknown {name: 'uname -a;lspci', threat_phase:"Unknown", threat_purpose: "Unknown", threat_category: "Unknown", time: "2022-07-21T00:02:03+0000"}),
(a)-[r:ATTACK {time: "2022-08-21T19:51:05+0000"}]->(b),
(b)-[:GO_TO {attack_id: r.id}]->(c)
ASo, what I'm trying to achieve is, I want to insert the relationship id from (a)->(b) into the relationship from (b)->(c). I already tries to use r.id as the relationship data, but it doesn't work. The query doesn't return error, but the (b)->(c) relationship didn't successfully stored the attack_id
To get the value of the object id of a node or an edge, you will use id(r) and NOT r.id. The property id is a user-defined property so you should define it while id(r) is a function created by neo4j to get the object id of r. Below is the correct query;
CREATE
(a:IP_ADDRESS {name: "224.36.71.118"}),
(b:TARGET {honeypot: "cowrie", target_post: "2222", target_protocol: "tcp", analyzer_id: "VM1"}),
(c:Unknown {name: 'uname -a;lspci', threat_phase:"Unknown", threat_purpose: "Unknown", threat_category: "Unknown", time: "2022-07-21T00:02:03+0000"}),
(a)-[r:ATTACK {time: "2022-08-21T19:51:05+0000"}]->(b),
(b)-[:GO_TO {attack_id: id(r)}]->(c)
Result:
If you use separate CREATE statements, it works perfectly. Try this
CREATE (t1:Test),
(t2:Test),
(t3:Test)
CREATE (t1)-[r:REL_TO]->(t2)
CREATE (t2)-[r2:REL_TO {idr: id(r)}]->(t3)
RETURN id(r), properties(r2)
which returns
╒═══════╤════════════════╕
│"id(r)"│"properties(r2)"│
╞═══════╪════════════════╡
│12 │{"idr":12} │
└───────┴────────────────┘

Neo4j - Project graph from Neo4j with GraphDataScience

So I have a graph of nodes -- "Papers" and relationships -- "Citations".
Nodes have properties: "x", a list with 0/1 entries corresponding to whether a word is present in the paper or not, and "y" an integer label (one of the classes from 0-6).
I want to project the graph from Neo4j using GraphDataScience.
I've been using this documentation and I indeed managed to project the nodes and vertices of the graph:
Code
from graphdatascience import GraphDataScience
AURA_CONNECTION_URI = "neo4j+s://xxxx.databases.neo4j.io"
AURA_USERNAME = "neo4j"
AURA_PASSWORD = "my_code:)"
# Client instantiation
gds = GraphDataScience(
AURA_CONNECTION_URI,
auth=(AURA_USERNAME, AURA_PASSWORD),
aura_ds=True
)
#Shorthand projection --works
shorthand_graph, result = gds.graph.project(
"short-example-graph",
["Paper"],
["Citation"]
)
When I do print(result) it shows
nodeProjection {'Paper': {'label': 'Paper', 'properties': {}}}
relationshipProjection {'Citation': {'orientation': 'NATURAL', 'aggre...
graphName short-example-graph
nodeCount 2708
relationshipCount 10556
projectMillis 34
Name: 0, dtype: object
However, no properties of the nodes are projected. I then use the extended syntax as described in the documentation:
# Project a graph using the extended syntax
extended_form_graph, result = gds.graph.project(
"Long-form-example-graph",
{'Paper': {properties: "x"}},
"Citation"
)
print(result)
#Errors
I get the error:
NameError: name 'properties' is not defined
I tried various variations of this, with or without " ", but none have worked so far (also documentation is very confusing because one of the docs always uses " " and in another place I did not see " ").
Also, note that all my properties are integers in the Neo4j db (in AuraDS), as I used to have the error that String properties are not supported.
Some clarification on the correct way of projecting node features (aka properties) would be very useful.
thank you,
Dina
The keys in the Python dictionaries that you use with the GraphDataScience library should be enclosed in quotation marks. This is different from Cypher syntax, where map keys are not enclosed with quotation marks.
This should work for you.
extended_form_graph, result = gds.graph.project(
"Long-form-example-graph",
{'Paper': {"properties": "x"}},
"Citation"
)
Best wishes,
Nathan

Losing some z3c relation data on restart

I have the following code which is meant to programmatically assign relation values to a custom content type.
publications = # some data
catalog = getToolByName(context, 'portal_catalog')
for pub in publications:
if pub['custom_id']:
results = catalog(custom_id=pub['custom_id'])
if len(results) == 1:
obj = results[0].getObject()
measures = []
for m in pub['measure']:
if m in context.objectIds():
m_id = intids.getId(context[m])
relation = RelationValue(m_id)
measures.append(relation)
obj.measures = measures
obj.reindexObject()
notify(ObjectModifiedEvent(obj))
Snippet of schema for custom content type
measures = RelationList(
title=_(u'Measure(s)'),
required=False,
value_type=RelationChoice(title=_(u'Measure'),
source=ObjPathSourceBinder(object_provides='foo.bar.interfaces.measure.IMeasure')),
)
When I run my script everything looks good. The problem is when my template for the custom content tries to call "pub/from_object/absolute_url" the value is blank - only after a restart. Interestingly, I can get other attributes of pub/from_object after a restart, just not it's URL.
from_object retrieves the referencing object from the relation catalog, but doesn't put the object back in its proper Acquisition chain. See http://docs.plone.org/external/plone.app.dexterity/docs/advanced/references.html#back-references for a way to do it that should work.

What's wrong with my filter query to figure out if a key is a member of a list(db.key) property?

I'm having trouble retrieving a filtered list from google app engine datastore (using python for server side). My data entity is defined as the following
class Course_Table(db.Model):
course_name = db.StringProperty(required=True, indexed=True)
....
head_tags_1=db.ListProperty(db.Key)
So the head_tags_1 property is a list of keys (which are the keys to a different entity called Headings_1).
I'm in the Handler below to spin through my Course_Table entity to filter the courses that have a particular Headings_1 key as a member of the head_tags_1 property. However, it doesn't seem like it is retrieving anything when I know there is data there to fulfill the request since it never displays the logs below when I go back to iterate through the results of my query (below). Any ideas of what I'm doing wrong?
def get(self,level_num,h_key):
path = []
if level_num == "1":
q = Course_Table.all().filter("head_tags_1 =", h_key)
for each in q:
logging.info('going through courses with this heading name')
logging.info("course name filtered is %s ", each.course_name)
MANY MANY THANK YOUS
I assume h_key is key of headings_1, since head_tags_1 is a list, I believe what you need is IN operator. https://developers.google.com/appengine/docs/python/datastore/queries
Note: your indentation inside the for loop does not seem correct.
My bad apparently '=' for list is already check membership. Using = to check membership is working for me, can you make sure h_key is really a datastore key class?
Here is my example, the first get produces result, where the 2nd one is not
import webapp2 from google.appengine.ext import db
class Greeting(db.Model):
author = db.StringProperty()
x = db.ListProperty(db.Key)
class C(db.Model): name = db.StringProperty()
class MainPage(webapp2.RequestHandler):
def get(self):
ckey = db.Key.from_path('C', 'abc')
dkey = db.Key.from_path('C', 'def')
ekey = db.Key.from_path('C', 'ghi')
Greeting(author='xxx', x=[ckey, dkey]).put()
x = Greeting.all().filter('x =',ckey).get()
self.response.write(x and x.author or 'None')
x = Greeting.all().filter('x =',ekey).get()
self.response.write(x and x.author or 'None')
app = webapp2.WSGIApplication([('/', MainPage)],
debug=True)

Resources