Naming resources prior to creation using Neo4j Restful API - rest

This is for people with knowledge on REST and Neo4j.
Is it possible to name a node before creating it in Neo4j ?
Typical Restful thing, you create a URI "XXX/db/data/node/mynode" and you want to create a node with this identifier if it is not existent in the moment.
For all that I have been researching (and testing) to the present moment, the answer is : "no it is not possible, neo4j will just always automatically give ids to the created nodes and the attempt to do create a URI and use POST to cause its creation will result in 405"
Thanks in advance.

That's correct, you can't set the id of a node. What you can do is to add some other kind of id as a property, see create node with properties. Just make sure it's indexed automatically and then you can query that index for exact matches.

Related

REST new ID with DDD Aggregate

This question seemed fool at first sight for me, but then I realized that I don't have a proper answer yet, and interestingly also didn't find good explanation about it in my searches.
I'm new to Domain Driven Design concepts, so, even if the question is basic, feel free to add any considerations to it.
I'm designing in Rest API to configure Server Instances, and I came up with a Aggregate called Instance that contains a List of Configurations, only one specific Configuration will be active at a given time.
To add a Configuration, one would call an endpoint POST /instances/{id}/configurations with the body on the desired configuration. In response, if all okay, it would receive a HTTP 204 with a Header Location containing the new Configuration ID.
I'm planning to have only one Controller, InstanceController, that would call InstanceService that would manipulate the Instance Aggregate and then store to the Repo.
Since the ID's are generated by the repository, If I call Instance.addConfiguration and then InstanceRepository.store, how would I get the ID of the newly created configuration? I mean, it's a List, so It's not trivial as calling Instance.configuration.identity
A option would implement a method in Instance like, getLastAddedConfiguration, but this seems really brittle.
What is the general approach in this situation?
the ID's are generated by the repository
You could remove this extra complexity. Since Configuration is an entity of the Instance aggregate, its Id only needs to be unique inside the aggregate, not across the whole application. Therefore, the easiest is that the Aggregate assigns the ConfigurationId in the Instance.addConfiguration method (as the aggregate can easily ensure the uniqueness of the new Id). This method can return the new ConfigurationId (or the whole object with the Id if necessary).
What is the general approach in this situation?
I'm not sure about the general approach, but in my opinion, the sooner you create the Ids the better. For Aggregates, you'd create the Id before storing it (maybe a GUID), for entities, the Aggregate can create it the moment of creating/adding the entity. This allows you to perform other actions (eg publishing an event) using these Ids without having to store and retrieve the Ids from the DB, which will necessarily have an impact on how you implement and use your repositories and this is not ideal.

Retrieving a node solely based on its Tag

A customer has implemented an OPC-UA server and has provided some documentation for us to access it. The only information we have is the endpoint to contact the server at and the tags that the data points are linked to.
I have to implement a client without having access to the server to test it with. Is this enough information to go by? I imagine we would at least need some namespace uri. From what I understand, in order to use a function such as translateBrowsePathsToNodeIds I would also need to know some namespace ID's.
For instance, in python-opcua it would be something like:
mynode = client.uaclient.translate_browsepaths_to_nodeids(ua.QualifiedName("StaticData", 3)) (which somehow is not working but that's another question)
It doesn't help that the client examples I find somehow all use hardcoded namespace ID's.
TranslateBrowsePathToNodeIds is generally used when programming against type definitions where you know what the path of BrowseNames will be because they are defined by the type definition of each node in the path.
If this doesn't sound like your situation then you should push back for the documentation to include the NodeIds of all the Nodes you need to access.

REST API with segmented/path ID

I am trying to design a REST API for a system where the resources are essentially identified by path-like addresses with varying numbers of segments. For example, a "Schema" resource could be represented on the file system as follows:
/Resources/Schemas/MyFolder2/MyFolder5/MySchema27
The file-system path /Resources/Schemas/ is the root folder for all Schemas, and everything below this is entirely user defined (as far as folder depth and folder naming). So, in the example above, the particular Schema would be uniquely identified by the following address (since "MySchema27" by itself would not necessarily be unique):
/MyFolder2/MyFolder5/MySchema27
What would be the best way to refer to a resource like this in a REST API?
If I have a /schemas collection my REST URL could be:
/schemas/MyFolder2/MyFolder5/MySchema27
Would that be a reasonable approach? Are there better ways of handling this?
I could, potentially, do a 2-step approach where the client would first have to search for a Schema using the Schema address (in URL parameters or in the request body), which would then return a unique ID that could then be used with a more traditional /schemas/{id} design. Not sure that I like that, though, especially since it would mean tracking a separate ID for each resource. Thoughts? Thanks.
The usual way to add a resource to your "folder" /Resources/Schemas/ is to make a POST request on it with the body of this POST request containing a representation of the resource to add, then the server will take care of finding the next free {id} and and setting the new resource to /Resources/Schemas/{id}.
Another approach is to, as you said, make a GET request on /Resources/Schemas/new which would return the next free {id}, and then, make a second request PUT directly on /Resources/Schemas/{id}. However this second approach is not as secure as the first since two simultaneous request could lead to the same new {id} returned and so the second PUT would erase the first. You can secure this with some sort of reservation mechanism.
This is called as Resource Based URI approach for building REST services . Follow these wonderful set of video tutorials to understand more about them and learn how to implement too . https://javabrains.io/courses/javaee_jaxrs

REST url for unique resource (url with singular ?)

I have a webserver with some configuration properties and I want to be able to change them using a REST API.
Example
{
"maxUsers" : 10,
"refreshPeriodInMin" : 5
}
I would like to represent this with a "configuration" object. According to REST principle I believe the best way to do it is :
GET/PUT/POST/DELETE /configurations/{id}
But in my case I have only one configuration object and I do not like the idea of have to query
GET /configurations
just for one object.
Because there is only one object the easiest solution I found is to use id=default
Would give something like
GET /configurations/default
Is there a better way to represent a "unique" resource ? As mentionned by djmorton in the comments would /configuration be correct in a REST world ?
Another solution I though about would be to have one object per property. This would give
GET /properties/maxUsers
Problem with that solution is that you need to know the name of property to be able to query it. PLus you will make several queries if you have multiple changes to make.
Keep the resource singular if it truly represents a singular thing. If you will only have one, there is no reason not to simply PUT to that resource when you want to create or update it, and GET from that resource when you want to retrieve it.
If it can not be deleted, return a 405 METHOD NOT ALLOWED on DELETE requests. If it can be deleted, a DELETE request to that resource is acceptable, after which GET requests can return a 404 NOT FOUND.
In many ways, adding an id element to the path like /configuration/default would probably confuse users because they might expect that they would be able to POST new configurations to /configuration in addition to the default one.
The key is to do something that is sensible and intuitive to consumers of the API.

Neo4j merge statement with id

I'm trying to do a merge statement. I'm trying to get the node with his node id, the problem that merging doesn't allow me to use 'where id(node)=nodeId'.
Something like:
merge( user:User) where id(user)=111
on create set user =
{facebookId:"13",name:"",gender:"",pushId:"", picoAccessToken:"",
accessTokenExpires:""}
on match set user +=
{facebookId:"13",name:"",gender:"",pushId:"",picoAccessToken:"",
accessTokenExpires:""}
return user
General question, should I use the node id to retrieve nodes? or should I add an id property to the node.
You can't use the "ID()" function with MERGE because it behaves as "MATCH or CREATE" and you can't assign internal ids manually to nodes.
On the other hand, YES! it is better to use an id generation at the application level that you will assign to nodes OR use the GraphAware UUID plugin that will do it for you https://github.com/graphaware/neo4j-uuid/tree/master.
Relying on nodes internal ids is considered as bad practice as ids of deleted nodes are reused in the database lifecycle.
Michael Hunger from Neo Technology has already answered the question regarding internal ids here on StackOverflow.
The bottom line is that the node id should not be used, rather they should be considered an implementation detail.
So, the recommended approach is to use your own id property*. This can be a UUID, some kind of counter or whatever id that is suitable for your project.
Personally I like the UUID-approach. They are easy to generate from any language (e.g. the UUID-class in Java). The are unique and it is obvious that the are generated.