I've been trying to create a graph using py2neo / neo4j but I'm constantly hitting problems with my script. The latest one being the following...
(bare in mind that i am also new to python. sorry!)
Here is the code:
from py2neo import neo4j, node
graph = neo4j.GraphDatabaseService("http://localhost:7474/db/data/")
graph.clear()
i_word = graph.get_or_create_index(neo4j.Node, "i_word")
i_token = graph.get_or_create_index(neo4j.Node, "i_token")
labels = {"TOKEN"}
properties = {"name": "Ana"}
a_node = node(*labels, **properties)
c_node, = graph.create(a_node)
I'm getting the following error:
... py2neo/neo4j.py", line 237
... TypeError: Cannot cast node from (('TOKEN',), {'name':'Ana'})
Any ideas? many thanks for your time.
rgds,
Pedro
The node function in py2neo 1.6 does not have label support. You can only supply properties for creation and then later add labels. The alternative will be to use a Cypher expression such as:
CREATE n:TOKEN {name:'Ana'}
As a side note, bear in mind also that labels are generally be written in TitleCase rather than UPPER_CASE.
Related
I have the following paramObj and dbQuery
paramObj = {
email: newUser.email,
mobilenumber: newUser.telephone,
password: newUser.password,
category: newUser.category,
name: newUser.name,
confirmuid: verificationHash,
confirmexpire: expiryDate.valueOf(),
rewardPoints: 0,
emailconfirmed: 'false',
paramVehicles: makeVehicleArray,
paramVehicleProps: vehiclePropsArray
}
dbQuery = `CREATE (user:Person:Owner {email:$email})
SET user += apoc.map.clean(paramObj,
['email','paramVehicles','paramVehiclesProps'],[])
WITH user, $paramVehicles AS vehicles
UNWIND vehicles AS vehicle
MATCH(v:Vehicles {name:vehicle})
CREATE UNIQUE (user)-[r:OWNS {since: timestamp()}]->(v)
RETURN user,r,v`;
Then I tried to execute
commons.session
.run(dbQuery, paramObj)
.then(newUser => {
commons.session.close();
if (!newUser.records[0]) {........
I am getting
Error: {"code":"Neo.ClientError.Statement.SyntaxError","name":"Neo4jError"}
which doesn't direct me anywhere. Can anyone tell me what am I doing wrong here?
This is actually the first time I am using the query format .run(dbQuery, paramObj) but this format is critical to my use case. I am using Neo4j 3.4.5 community with apoc plugin installed.
Ok...so I followed #inversFalcon suggestion to test in browser and came up with following parameters and query that closely match the ones above:
:params paramObj:[{ email:"xyz123#abc.com", mobilenumber:"8711231234",password:"password1", category:"Owner",name:"Michaell",vehicles:["Toyota","BMW","Nissan"],vehicleProps: [] }]
and query
PROFILE
CREATE (user:Person:Owner {email:$email})
SET user += apoc.map.clean($paramObj, ["email","vehicles","vehicleProps"],[])
WITH user, $vehicles AS vehicles
UNWIND vehicles AS vehicle
MATCH(v:Vehicles {name:vehicle})
MERGE (user)-[r:OWNS {since: timestamp()}]->(v)
RETURN user,r,v;
Now I get
Neo.ClientError.Statement.TypeError: Can't coerce `List{Map{name -> String("Michaell"), vehicles -> List{String("Toyota"), String("BMW"), String("Nissan")},.......
I also reverted to neo4j 3.2 (re: an earlier post by Mark Needham) and got the same error.
You should try doing an EXPLAIN of the query using the browser to troubleshoot it.
A few of the things I'm seeing here:
You're referring to paramObj, but it's not a parameter (rather, it's the map of parameters you're passing in, but it itself is not a parameter you can reference in the query). If you need to reference the entire set of parameters being passed in, then you need to use nested maps, and have paramObj be a key in the map that you pass as the parameter map (and when you do use it in the query, you'll need to use $paramObj)
CREATE UNIQUE is deprecated, you should use MERGE instead, though be aware that it does behave in a different manner (see the MERGE documentation as well as our knowledge base article explaining some of the easy-to-miss details of how MERGE works).
I am not sure what caused the coercion error to disappear but it did with the same query and I got a "expected parameter error" this was fixed by using $paramObj.email, etc. so the final query looks like this:
CREATE (user:Person:Owner {email: $paramObj.email})
SET user += apoc.map.clean($queryObj, ["email","vehicles","vehicleProps"],[])
WITH user, $paramObj.vehicles AS vehicles
UNWIND vehicles AS vehicle
MATCH(v:Vehicles {name:vehicle})
MERGE (user)-[r:OWNS {since: timestamp()}]->(v)
RETURN user,r,v;
which fixed my original problem of how to remove properties from a map when using SET += map.
Kindly help me to resolve this issue. I am following the tutorial on this link: https://www.kernix.com/blog/an-efficient-recommender-system-based-on-graph-database_p9 . I am unable to modify the following so that it could comply with the new format of py2neo v3 where graph.run is used instead of graph.cypher.begin(). The purpose of the code below is to Create the nodes relative to Users, each one being identified by its user_id and "MERGE" request : creates a new node if it does not exist already
tx = graph.cypher.begin()
statement = "MERGE (a:`User`{user_id:{A}}) RETURN a"
for u in user['id']:
tx.append(statement, {"A": u})
tx.commit()
Thank you very much in advance
With v3 of py2neo your snippet would look like this:
tx = graph.begin()
statement = "MERGE (a:`User`{user_id:{A}}) RETURN a"
for u in user['id']:
tx.run(statement, {"A": u})
tx.commit()
begin() is a method on the Graph class, which will create a new transaction.
Transaction.run will send a Cypher statement to the server for execution - but not commit the transaction until Transaction.commit is called.
Im trying to modify an epl by compiling it using the compileEPL() method and add more to e.g the where clause, however im havin trouble getting it work.
Lets say this is my epl:
select * from event where A = 1
and I want to add another where condition using the AND
and I compile the epl using compileEPL()
model.getWhereClause().getChildren().add(Expressions.and()
.add(Expressions.eq("B", )));
instead of giving me:
select * from event where A = 1 and B = 2 it just gives ..where A = 1 and not adding the new where clause.
Am I doing it wrong? The EPStatementObjectModel works fine for building an object EPL from scratch but not when compiling it and adding or modify it.
Does anyone know? Thanks.
The where-clause is rooted in an EQ since "A=1".
Expression equalsExpr = model.getWhereClause();
So construct an AND clause that holds the old EQ and the new EQ.
Expression and = Expressions.and().add(equalsExpr).add(Expressions.eq("B", ...));
Finally set the "and" as the new where-clause:
model.setWhereClause(and);
In summary, when modifying expressions to add "and": when old expression is not itself an AND you should build an AND node and add the old expression and new ones.
I'm new to this python/biopyhton stuff, so am struggling to work out why the following code, pretty much lifted straight out of the Biopython Cookbook, isn't doing what I'd expect.
I'd have thought it'd end up with the interpreter display two list containing the same number, but all i get is one list and then a message saying TypeError: 'generator' object is not subscriptable.
I'm guessing something is going wrong with the Medline.parse step and the result of the efetch isn't being processed in a way that allows subsequent interation to extract the PMID values. Or, the efetch isn't returning anything.
Any pointers at to what I'm doing wrong?
Thanks
from Bio import Medline
from Bio import Entrez
Entrez.email = 'A.N.Other#example.com'
handle = Entrez.esearch(db="pubmed", term="biopython")
record = Entrez.read(handle)
print(record['IdList'])
items = record['IdList']
handle2 = Entrez.efetch(db="pubmed", id=items, rettype="medline", retmode="text")
records = Medline.parse(handle2)
for r in records:
print(records['PMID'])
You're trying to print records['PMID'] which is a generator. I think you meant to do print(r['PMID']) which will print the 'PMID' entry in the current record dictionary object for each iteration. This is confirmed by the example given in the Bio.Medline.parse() documentation.
This might be real newbie question but please bear with me as I am new. I looked at this code sample in documentation.
graphClient
.Cypher
.Start(new {
n1 = "custom",
n2 = nodeRef,
n3 = Node.ByIndexLookup("indexName", "property", "value"),
n4 = Node.ByIndexQuery("indexName", "query"),
r1 = relRef,
moreRels = new[] { relRef, relRef2 },
r2 = Relationship.ByIndexLookup("indexName", "property", "value"),
r3 = Relationship.ByIndexQuery("indexName", "query"),
all = All.Nodes
});
In the example above I would like to get a relationship by IndexLookup. So I created a Relationship Index
_graphClient.CreateIndex("item_relationship_idx", new IndexConfiguration
{
Provider = IndexProvider.lucene,
Type = IndexType.exact
},
IndexFor.Relationship);
Question - How do I get a relationship created by _graphClient.CreateRelationship into an index. Most of the samples provided just show getting NodeReference into an Index. I am sure I am missing something obvious. Any help would be appreciated.
Update to Neo4jClient 1.0.0.568 or above and you'll find the (new) support for relationship indexing, consistent with how node indexing works.
(You should also look at Neo4j 2.0 and try and use the new indexing infrastructure though. No point writing new code against old approaches.)
Update to Neo4jClient 1.0.0.568 or above and you'll find the (new) support for relationship indexing, consistent with how node indexing works.
Does that mean I can use the Create method or do I still need the CreateRelationship method? I have Neo4jClient 1.0.0.590 but I don't find it that obvious.