Create multiple relationships with py2neo - neo4j

I want to create multiple relationships between the same node using py2neo library. I used create if the relationship does not exist and merge when it exists. Here is a sample of my code :
def create_route(graph, sourcefile, airport_nodes):
with open(sourcefile, encoding="utf8") as csvfile:
reader = csv.DictReader(csvfile)
fieldnames = reader.fieldnames
for row in reader:
source_airport = row['origin']
destination_airport = row['destination']
source_airport_node = airport_nodes[source_airport]
destination_airport_node = airport_nodes[destination_airport]
node_properties = {'distance':row['distance']}
node_properties1 = {'duration': row['duration']}
graph.create(Relationship(source_airport_node, destination_airport_node,**node_properties1))
graph.merge(Relationship(source_airport_node, destination_airport_node, **node_properties))
The problem that It get only one relationship with the last attribute which is the distance.
Thank you

Related

Obtaining node id and parent id in cypher or with neomodel

I'm using neomodel and I have the following models:
class ForumElement(StructuredNode):
uid = UniqueIdProperty()
created_at = DateTimeProperty(default=dt.datetime.utcnow())
text = StringProperty()
is_visible = BooleanProperty(default=True)
picture = Relationship(Picture, 'HAS_PICTURE')
author = Relationship(User, 'HAS_USER')
class Post(ForumElement):
title = StringProperty(default="")
latitude = FloatProperty()
longitude = FloatProperty()
tags = Relationship(Tag, 'HAS_TAGS')
class Comment(ForumElement):
parent = Relationship(ForumElement, 'HAS_PARENT')
With that code I have in the database something like the image, where in blue we have "comments" and in pink we have "post".
Now, I would like to have as result of a query a list of couple <parent.uid, childen.uid>, how could I obtain that? Notice that the parent of a Comment could be a Post or another Comment
On neo4j you can use a basic Cypher query like this:
MATCH(c)-[:HAS_PARENT]->(p)
RETURN c.uid, p.uid
Just MATCH according to the pattern of one relationship with label HAS_PARENT and RETURN only the uid properties.
When used with neomodel on python, it can be called like this:
query = '''MATCH(c)-[:HAS_PARENT]->(p) RETURN c.uid, p.uid'''})
results, meta = db.cypher_query(query, {})
You can test it on mock data like this:
MERGE (mark:COMMENT {uid: "Mark"})
MERGE (lju:COMMENT {uid: "Lju"})
MERGE (praveena:COMMENT {uid: "Praveena"})
MERGE (zhen:POST {uid: "Zhen"})
MERGE (martin:COMMENT {uid: "Martin"})
MERGE (mark)-[:HAS_PARENT]-(lju)
MERGE (lju)-[:HAS_PARENT]-(praveena)
MERGE (praveena)-[:HAS_PARENT]-(zhen)
MERGE (martin)-[:HAS_PARENT]-(zhen)

How can i keep this table in the shown order?

Hello i have got a table, that uses string indexes:
shirt = {
["shirtwhite.png"] = "shirt_white.png",
["shirtwhite.png^[multiply:#3f3f3f"] = "shirt_white.png^[multiply:#3f3f3f",
["shirtwhite.png^[multiply:#ff0000"] = "shirt_white.png^[multiply:#ff0000",
["shirtwhite.png^[multiply:#ff7f00"] = "shirt_white.png^[multiply:#ff7f00",
["shirtwhite.png^[multiply:#ffff00"] = "shirt_white.png^[multiply:#ffff00",
["shirtwhite.png^[multiply:#00ff00"] = "shirt_white.png^[multiply:#00ff00",
["shirtwhite.png^[multiply:#0000ff"] = "shirt_white.png^[multiply:#0000ff",
["shirtwhite.png^[multiply:#9f00ff"] = "shirt_white.png^[multiply:#9f00ff",
},
Theese are t-shirt-textures for an editable game-character-skin (with colour-values for different colors).
There are some more of theese tables in the code, for other parts of the character-skin
how can I keep the table in it´s shown order, while it´s loaded in this code-snippet?
The tzables are in a file "skins.lua" and the code-snippet is from another lua-file
character_creator = {}
character_creator.skins = dofile(minetest.get_modpath("character_creator") .. "/skins.lua")
local skins = character_creator.skins
local skins_array = {}
minetest.after(0, function()
local function associative_to_array(associative)
local array = {}
for key in pairs(associative) do
table.insert(array, key)
end
return array
end
skins_array = {
skin = associative_to_array(skins.skin),
hair = associative_to_array(skins.hair),
eyes = associative_to_array(skins.eyes),
shirt = associative_to_array(skins.shirt),
pants = associative_to_array(skins.pants),
}
end)
In Lua only arrays (positive integer-indexed tables) have "order" (can be iterated using ipairs); the hash tables (like the one you are working with) are unordered. If you want to iterate over a table like this in a specific order, you'd usually create an array with the keys, sorted them in the order you want and then iterate over that array extracting elements from your table.
There are also components (like ordered table) that may keep track of insertions and return results in the same order, if that's what you want.

Py2neo V3 adding relationships to transactions in a loop

Trying to add nodes and relationships in transactional manner using py2neo V3.
I would like to add the person and all their movies as one transaction.
I could not get nodes in the outer and inner loops to work in the same transaction. I'm pretty confident the relationship is not being added in a transactional manner either since I'm calling tx1.graph.
Neo4j V3.0.7
Py2Neo v3.1.2
from py2neo import Graph,Node,Relationship,authenticate, watch
from py2neo.ogm import GraphObject, Property, RelatedTo, RelatedFrom
class Movie(GraphObject):
__primarykey__ = "title"
title = Property()
class Person(GraphObject):
__primarykey__ = "name"
name = Property()
acted_in = RelatedTo(Movie)
People = ["John","Jane","Tarzan"]
Movies = [["John","Movie1"],["John","Move2"],["Jane","Movie3"],["Jane","Movie4"],["Tarzan","Movie4"]]
graph = Graph("http://localhost:7474")
for p in People:
print(p)
tx = graph.begin()
p1 = Person()
p1.name = p
tx.merge(p1)
tx.commit()
for m in Movies:
if m[0] != p:
continue
print(m[1])
tx1 = graph.begin() #did not work using original tx transaction
m1 = Movie()
m1.title = m[1]
tx1.merge(m1)
p1.acted_in.add(m1)
#tx1.merge(p1) #did not create relationship
#tx1.create(p1) #did not create relationship
tx1.graph.push(p1) # worked in adding relationship, but can't guarantee was part of the transaction
tx1.commit()
Try the following loop, which uses a single transaction for each Person and its relationships:
for p in People:
print(p)
tx = graph.begin()
p1 = Person()
p1.name = p
tx.merge(p1)
for m in Movies:
if m[0] != p:
continue
print(m[1])
m1 = Movie()
m1.title = m[1]
tx.merge(m1)
p1.acted_in.add(m1)
tx.graph.push(p1)
tx.commit()
Note: It would actually be more efficient to use a single transaction for processing multiple persons. But you would not want to handle too many (depending on your data model) at one time either, as that would risk making the server run out of memory.

Adwords API report segmenting

i'm trying to create google adwords report that will gain me
clicks,shows,cost,bounce,goal reach count
for each:
ad id, pharse id, goal id, day
(like group by)
There are a lot of different report types and i can't get how to create that kind of report.
Im using googleads-php-lib, so here is the code from example:
$selector = new Selector();
$selector->fields = array('Id', 'Clicks', 'Cost');
// Optional: use predicate to filter out paused criteria.
//$selector->predicates[] = new Predicate('Status', 'NOT_IN', array('PAUSED'));
// Create report definition.
$reportDefinition = new ReportDefinition();
$reportDefinition->selector = $selector;
$reportDefinition->reportName = 'Criteria performance report #' . uniqid();
$reportDefinition->dateRangeType = 'LAST_90_DAYS';
$reportDefinition->reportType = 'AD_PERFORMANCE_REPORT';
$reportDefinition->downloadFormat = 'CSV';
Sometimes you can't get all data in the same report. You can see all the report types in the AdWords Docs:
https://developers.google.com/adwords/api/docs/appendix/reports
You can add Segment in selector->fields
Example: ClickType is a segment so it will be implemented as given below.
$selector->fields = array('Id', 'Clicks', 'Cost', 'ClickType');
or with CriteriaReportWithAwql
$query = (new ReportQueryBuilder())
->select([
'CampaignId',
'CampaignName',
'Impressions',
'Clicks',
'Cost',
'ClickType',
'AccountCurrencyCode',
])
->from(ReportDefinitionReportType::CRITERIA_PERFORMANCE_REPORT)
->where('Status')->in(['ENABLED', 'PAUSED'])
->where('CampaignId')->in(['90045151'])
->during($startDate, $endDate)
->build();

Creating relationships taking too long in Neo4j using Neo4php

I have been trying to create nodes and relations ships for our new module with neo4jphp [https://github.com/jadell/neo4jphp/wiki].
I am using cypher queries for the same.
Creating nodes with below query:
$queryNodes = "CREATE (n:User { props } ) ";
$query = new Everyman\Neo4j\Cypher\Query($client, $queryNodes, array('props' => $arrNodeProperties));
$result = $query->getResultSet();
Creating relationships with below query:
$queryRelations = "
MATCH (authUser: User { userid: 0001 }),(friend)
WHERE friend.userid IN ['" . implode("','",$relations) . "']
CREATE UNIQUE (authUser)-[r:KNOWS { connection: 'user_friend' }]->(friend)";
So far node creation works gr8.
But when i try to create Unique relationships for the nodes, it takes too long....
Note:
There is unique constraint userid for label User, hence node with label user is indexed by Neo4j on property userid.
CREATE CONSTRAINT ON (user:User) ASSERT user.userid IS UNIQUE
Questions:
Is there any other way we can achieve creating unique relationships.
Can i use index on relationships?? If Yes how can I achieve the same.
You might try use use MERGE instead of CREATE UNIQUE. Additionally use a Cypher parameter for the fried's list instead of concatenation on client side, see http://docs.neo4j.org/chunked/stable/cypher-parameters.html
Finally I worked it out with few changes...
Thanks #MichaelHunger for the help.
So here is how i did it...
Creating Unique Nodes using MERGE, FOREACH, ON CREATE SET and params:
$queryNodes = "
FOREACH (nodeData IN {nodeProperties}|
MERGE (n:User { userid: nodeData.userid })
ON CREATE SET
n.login = nodeData.login,
n.userid = nodeData.userid,
n.username = nodeData.username,
n.name = nodeData.name,
n.gender = nodeData.gender,
n.profile_pic = nodeData.profile_pic,
n.create_date = timestamp()
ON MATCH SET
n.update_date = timestamp()
)
";
$query = new Everyman\Neo4j\Cypher\Query($client, $queryNodes, array('nodeProperties' => $arrNodeProperties));
$result = $query->getResultSet();
Creating Unique Relationships with below query:
$queryRelations = "
MATCH (authUser: User { userid: {authUserid} }), (friend:User)
WHERE friend.userid IN {friendUserIds}
CREATE UNIQUE (authUser)-[r:KNOWS { connection: 'user_friend' }]->(friend)
";
$query = new Everyman\Neo4j\Cypher\Query($client, $queryRelations, array('friendUserIds' => $arrFriendUserId, 'authUserid' => $authUserid));
$result = $query->getResultSet();
Please comment if we can improve the same even further.

Resources