Unique value in neo4j Nodes - neo4j

How can I define some value should be unique in Neo4j?
for example think I want to store users data in node,so username should be unique.Is there any way to do it like what we do in sql ( define username as unique properties )?

For this you will need to use a node index and the uniqueness features available within the API to ensure that only one node is filed under each key-value pair. If you're working with Neo4j embedded then have a look at:
http://api.neo4j.org/1.8/org/neo4j/graphdb/index/Index.html#putIfAbsent(T,
java.lang.String, java.lang.Object)
http://api.neo4j.org/1.8/org/neo4j/graphdb/index/UniqueFactory.html
For the REST interface, you may have uniqueness support already in the library that you are using or, if you are not using a library, this page should help:
http://docs.neo4j.org/chunked/milestone/rest-api-unique-indexes.html
As node structures are not enforced in the same way that record structures are enforced in most RDBMSs, there is no direct equivalent to the UNIQUE KEY feature that you mention. Index uniqueness should however give you the same end result.
Hope this helps
Nige

Related

What is the difference between randomUUID and GraphAware UUID in Neo4j?

I am currently using GraphAware UUID Library to generate UUID in neo4j, later I found out that it has a randomUUID() function to generate UUID, which one should be used?, will randomUUID() create unique id on server?
They both call java.util.UUID#randomUUID(), that's where the similarity between them ends.
The built-in Cypher's randomUUID() is a function, which you have to call manually in each cypher query where you want to assign a UUID.
The neo4j-uuid module is a set of extensions to Neo4j, which allow you to transparently assign UUID (or other types of ids - depending on configured id generator) to nodes and relationships, ensures the ids can't be changed or deleted. It also maintains an explicit index for the nodes / relationships. See the readme for the full feature set.
If your use case is simply to assign a uuid to (some) nodes or relationships then use the built in function. If you can take advantage of the other features of the neo4j-uuid module - use that.
For manual use cases, creating the UUID yourself in a Cypher query, they're functionally identical (GraphAware implemented this first I think, we got to it later). Yes the ids will be created on the server and will be unique, both
I believe GraphAware's UUID module covers more than just this, doing automatic assigning of UUIDs to newly created nodes and relationships and extra validation on top of that.

Neo4j.rb: autoincrement relationship attribute?

Is it possible to autoincrement an ActiveRel attribute? In contrast to ActiveRecord, it doesn't seem that ActiveNode/ActiveRel support autoincrement attributes out-of-the-box.
I considered using before_save to manually generate an id. However, it appears that it's not possible to order relationships (to find the previous highest id).
How does one implement autoincrementing ids? (I know Neo4j.rb generates UUIDs but this application requires a separate incremental serial number)
There is the auto-incrementing ID from Neo4j which starts at 0 independently for nodes and relationships. It can (I think) be depended on for referring to nodes in the short-term (i.e. seconds), but not in the long term as they may get cleaned up and moved around by Neo4j for performance.
If you're thinking about putting IDs on relationships what you're doing may not be the right modeling approach for Neo4j (though I couldn't say for sure without details). Relationships themselves can't be queried directly, but rather can only be accessed via first finding nodes. I think it would make sense to have an incrementing ID which is unique for all relationships relative to a node, but not globally. This is also why Neo4j.rb doesn't generate UUIDs for relationships. You may want to consider representing the relationships as intermediate nodes.
If you want to implement an incrementing ID on an ActiveNode model, before_save should be a fine way to do it.

Set a transient property on a node neo4j

Is there way to set a transient property on nodes returned by a cypher query such that it is only visible to the user running the query.
This would allow us offload some controller logic directly into Neo4j and reduce business logic queries.
Currently I have a list that is returned by
List<Post> newsFeed (Long uid) {}
Post is a relationship between a User and News node.
I have two sub-classes of the Post object:
BroadcastedPost
MentionedPost
I have two cypher queries that return the posts that a user should see.
List broadcasts obtained from
MATCH (user:PlatformUser)-[:BROADCASTED]->post RETURN post;
List mentionedPost obtained from
MATCH (user:PlatformUser)-[:MENTIONED]->post RETURN post;
I then use Java instanceof to determine what kind of post this is. Depending on the type I am able to do some further application logic.
This however is inefficient because I should be able to combine both queries into one super query using the UNION operator
i.e List newsFeed is obtained directly by querying
MATCH (user:PlatformUser)-[:BROADCASTED]->post RETURN post UNION MATCH (user:PlatformUser)-[:MENTIONED]->post RETURN post;
However, how can I tell what kind of post this. I was hoping I could use the SET operator transiently to know which kind of post this is but I believe this is used to persist a property.
Neo4j 2.2 recently added authentication, which it had lacked in previous releases, but it's still only really one user; you set a login/password to secure access to the database, but adding additional users takes extra work and isn't something obvious to do out of the box.
Now what you're asking for has to do with securing per-user access to particular types of data. Since neo4j doesn't have much of a user management feature right now, what you're asking for can't be done inside of neo4j because in order to secure this data away from Joe or Bob, the DBMS would have to know that it's dealing with Joe or Bob.
What you're trying to do is usually enforced by the application layer by people writing neo4j applications right now. So it can be done, but it's done within your custom code and not by the database directly.

Understanding Neo4j, creating unique nodes

I'm trying to wrap my head around how Neo4j works and how I can apply it to my problem. I thought it should be really easy and a matter of minutes, but I'm stuck.
I have data in MongoDB, say User and Item. What I want is connecting User and Item in a graph with a LIKE relationship (maybe with a score). Later I want to do things like recommending items based on connections, basic stuff.
But how do I get the data into Neo4j? Every document in MongoDB has an unique _id, so I though I could just throw both _ids into Neo4j and have them connected. What I found so far is that it's not even possible to have unique nodes based on the _id field (Neo4j has numeric incremented ids), which is only possible with some "hack" (https://github.com/jexp/app-net-graph/blob/master/lib/appnet.rb#L11) or using MERGE (I'm stuck on < 2.0). Even their examples on the website add the same node again if executed multiple times. I think I have a fundamental misunderstanding of how to use Neo4j. Maybe I'm too spoiled by redis, where I can put strings in and and it just works. Redis' sets aren't feasible though for complex graphs, only for simple connections.
Maybe someone can help me with a simple cypher example of how to add two nodes foo and bar and have them connected with a LIKE connection. And the operation should be idempotent, no matter if none or all of the nodes/relationships already existed before execution.
I'm accessing Neo4j via REST, in particular using this node module https://github.com/thingdom/node-neo4j
You could define your external ID as extra property on your nodes. Then depending on if your are using SpringData or not, you can insert the data.
If you are using SpringData, you can configure your external ID as unique index and then normally save you nodes(consider though, that inserting a duplicated ID will overwrite the existing one).
If you are using the plain java API, you can create unique nodes as described here:
http://docs.neo4j.org/chunked/stable/tutorials-java-embedded-unique-nodes.html#tutorials-java-embedded-unique-get-or-create
EDIT:
As for a sample query, does this help you?
http://console.neo4j.org/?id=b0z486
With the java api you would do it like this
firstNode = graphDb.createNode();
firstNode.setProperty( "externalID", "1" );
firstNode.setProperty( "name", "foo" );
secondNode = graphDb.createNode();
secondNode.setProperty( "externalID", "2" );
secondNode.setProperty( "name", "bar" );
relationship = firstNode.createRelationshipTo( secondNode, RelTypes.Likes );
I suggest you read some tutorials here: http://docs.neo4j.org/chunked/stable/tutorials-java-embedded-hello-world.html
Given you are using Neo4J1.9, have you tried creating a unique index on your _ID column?
Try this article from the docs
If you were using Neo4j2, then this article is helpful

optimistic concurrency with neo4j using the REST API

Is there any way to implement optimistic concurrency during updating and creating neo4j nodes using the REST API? I'd like to create a user node with a unique name only if that name doesn't exist. Don't want two users to accidentally overwrite each other if they pick the same username at the same time.
Additionally, I'd could also have something like an incrementing version number to check for concurrency on the node. In SQL I would normally have an update with a where clause that checks for id and version number. Is there something similar I can do with cypher that would be easy to implment and wouldn't require me to type all the property names out into a long query?
You could try a unique index: http://docs.neo4j.org/chunked/stable/rest-api-unique-indexes.html
Cypher "CREATE UNIQUE" syntax may also be a help: http://docs.neo4j.org/chunked/stable/query-create-unique.html

Resources