I'm writing a python 3.6 application that uses Neo4j as a backend with the official python driver. I'm new to Neo4j and Cypher. Data coming into the database needs to replace previous 'versions' of that data. I'm attempting to do this by creating a root node, indicating version. Eg.
MATCH (root:root_node)-[*..]->(any_node:) DETACH DELETE root, any_node
CREATE(root:new_root_node)
...
...
... represents all the new data i'm attaching to the new_root_node
The above doesn't work. How do I incorporate DELETE and CREATE statements in one transaction?
Thanks!
There's not a problem with DELETE and CREATE statements in a single transaction.
There are two problems here needing fixing.
The first is with (anynode:). The : separates the variable from the node label. If : is present, then the node label must also be present, and because no label is supplied here you're getting an error. To fix this, remove : completely like so: (anynode)
The second problem is with CREATE(root:new_root_node). The problem here is that the root variable is already in scope from your previous MATCH, so you'll need to use a different variable.
Also, your :new_root_node label doesn't seem useful, as any previously created queries for querying data from the root node will need to change to use the new label. I have a feeling you might be misunderstanding something about Neo4j labels, so a quick review of the relevant documentation may be helpful.
Related
I'm trying to create a model in SQLAlchemy, but I'm having a hard time finding out what is the best way. I currently have a class called returns, which I want to give an additional variable. A state of which the return is in. So for example, a return can be expected, received or processed. However, in the Flask application I want to show the user a nice string. For example; processed should become "Waiting for reimboursment".
The problem however is, I don't want to send these strings to the database, since I might change them in the future or add statusses. Therefore I want some kind of translation to be made between the value saved in the DB and the 'string' value. I have tried solving this by using Enums, but it is not possible to create the 'string' values. I would like something like this to return either the 'key' or the 'value', where only the key is saved in the database.
return.status.key
return.status.value
I have tried looking for a solution but was not able to find anything that seems to be fit.
What is the best practice for these kinds of requirements?
While working with the Enterprise Architect API I have noticed that when you export an EA project to XMI, several different kinds of elements get an attribute called ea_localid. That means in the XMI you'll find a tag that has the ea_localid as an attribute. This attribute seems to be used to reference source and target of connecting elements (at least this is valid for 'transitions', as we are working with State Machine diagrams).
So far, so good. Now the problem for my intended usage is that these values seem to be newly distributed every time you do an import and an export. EDIT: it is not quite clear to me when exactly during this process. EDIT #2 It seems to happen on import.
That means after having exported your project, reimporting it, changing nothing and then exporting it again gives the generated XMI document a set of different ea_localid values. Moreover, it seems that some values that used to belong to one element can now be used for an entirely different one.
Does anybody know anything about the distribution mechanism? Or, even better, a way of emulating it? Or a way to reset all counters?
As far as I've seen, generally there seem to be different classes of elements and within these classes a new ea_localid for the next element is generated by counting +1. So the first one has the value 1, then the next one 2 and so on.
My goal here is doing 'roundtrips' (XMI --> project --> XMI ...) and always getting the same ea_localid values, possibly by editing the XMI document after export. Any help or suggestions would be highly appreciated. Cheers
The ea_localid represents the elementID of elements (or AttributeID for attributes etc...)
In EA each "thing" has two ID's. A numeric ID, and a GUID.
The numeric ID (e.g. t_object.Object_ID) is used as key in most relations, but this is not stable.
Things like importing XMI files can reset the numeric ID's. This explains why the ea_localID changes.
If you are looking for a stable ID you should use the GUID. This one is guaranteed to stay the same, even after exporting and importing to other models. (as long as you don't set the flag Strip GUIDs when importing)
In the xmi file you'll find those stable id's in the attribte xmi.id
e.g
<UML:Class name="Aannemer" xmi.id="EAID_04A526DF_7F07_4475_8E65_16D2D88CEECD" visibility="public" namespace="EAPK_0345C8A9_9E8F_42c5_9931_CB842233B11B" isRoot="false" isLeaf="false" isAbstract="false" isActive="false">
This value corresponds to the ea_guid columns in each of the tables.
So, after some testing I have found out that regarding the aforementioned goal of doing a roundtrip (xmi --> import to EA --> xmi) and always getting the exact same document, the easiest solution is ...
running a filter over the xmi that just deletes all nodes containing ea_localid, ea_sourceID (sic!) and ea_targetID values.
On reimport EA will just assign them new values. The information regarding source and target of 'transitions' and other connecting elements is also stored with the GUID, so there is no loss of information.
I am writing a web app with a single neo4j database as the datastore. Different users have their own separate charts. I have checked other documentation and found that neo4j doesn't have a concept of schema and instead it is suggested that labels are used against every node to indicate which graph it belongs to.
I am writing a middleware for the web app in Python which deals with user logins and sends queries onwards to the database. I am building a webservice in this middleware which accepts a cipher query string and returns the query result. Before it forwards the query string on to the database it needs to alter it, adding a label depending on the logged in user.
I need to build a function as follows:
def query_for_user(origional_query, users_label):
return XXX
My first idea on how to do this is to use string processing based on information here: https://neo4j.com/docs/getting-started/current/cypher-intro/patterns/
Every node in a query is surrounded by brackets so I could replace every part of the query inside brackets with a new version. The brackets always seem to start with a node identifier so I could read past this and add the required label. Seems like it would work but would be error prone and brittle because I don't know all the features of cpher.
Does anyone know of a more elegant way of achieving my goal? Is there a cypher parser somewhere that I could use instead of string manipulation?
Neo4j labels are not meant to be used to separate nodes into different "graphs".
A label is meant to be used as a node "type". For example, "Person" would be an example of a typical label, but having a huge number of labels like "User049274658188" or "Graph93458428834" would not be good practice.
As appropriate, nodes should have a "type"-like label, and can include a property (say, id) whose value is a unique identifier. Your queries can then start by matching a specific label/id combination in order to indicate which "graph" you want to work on. All other nodes in that "graph" would be linked to that start node via relationship paths.
And typically one would generate Cypher from raw data, not Cypher templates. However, if you really want to use Cypher templating, the templates could just contain Cypher parameters, as in:
MATCH (p:Person)-[:LIVES_AT]->(a:Address) WHERE p.id = $personId RETURN p, a;
Your client code will just need to provide the parameter values when invoking the query.
Is there a possibility to reset the indices once I deleted the nodes just as if deleted the whole folder manually?
I am deleting the whole database with node.delete() and relation.delete() and just want the indices to start at 1 again and not where I had actually stopped...
I assume you are referring to the node and relationship IDs rather than the indexes?
Quick answer: You cannot explicitly force the counter to reset.
Slightly longer answer: Generally speaking, these IDs should not carry any relevance within your application. There have been a number of discussions about this within the Neo4j mailing list and Stack Overflow as the ID is an internal artifact and should not be used like a primary key. It's purpose is more akin to an in-memory address and if you require unique identifiers, you are better off considering something like a UUID.
You can stop your database, delete all the files in the database folder, and start it again.
This way, the ID generation will start back from 1.
This procedure completely wipes your data, so handle with care.
Now you certainly can do this using Python.
see https://stackoverflow.com/a/23310320
I'm fairly new to neo4j. I've played a little bit with cypher and REST API. I want to be able to create a leaf node along certain path, consider these nodes are some types of events. I wouldn't know during run time the id of the node this event will be attached to. I need to either do a look-up and then get the id of the node and then create my new node.
So during run time I was hoping I can do a MATCH using cypher to get the node to which I can attach the event and CREATE new node along with the relationship to the existing node returned by MATCH. So I came across the cypher cheat sheet which has a read-write-return query which I thought would be good fit. But there is nothing much mentioned about it in documentation or may be I'm not a super googler!!
Could someone please tell me if this(read-write-return) is the right/valid approach?
Many Thanks!
Yep. That's a good approach. That's one of the nice things about how CREATE works in Cypher. You can also optionally use create unique which creates the rel/node at the same time. Something like:
start n=node(1)
create unique n-[:event]->(event {prop:"val"})
return n, event;
Or without create unique:
start n=node(1)
create (event {prop:"val"}), n-[:event]->event
return n, event;