neo4j registering object into field - neo4j

Is it possible to store an object in a field with Cypher so that the node will return some fields as
field.prop.array[0].prop1
field.prop.array[0].prop2
field.prop.array[1].prop1
field.prop2.prop3.prop4
and if so: what's the query to do it? (I've been able to store only 1 level deep objects)

In Neo4j property values can be primitives, Strings or arrays of them, see http://docs.neo4j.org/chunked/stable/graphdb-neo4j-properties.html.
To build up more nested structures you should make them explicit in the graph. A nested property might become a node that connected to the originating node.

Related

Neo4j OGM Filter query against array

I'm trying to build a small property searching system. I'm using spring boot with a neo4j database and I'm trying to query from the neo4j database using filters becasue i need the querying to be dynamic too. In my use case properties has features such as electricity, tap water, tilled roof, etc. Property & Feature are nodes, Feature node has an attribtue named 'key', a Property node is linked to many Feature nodes by rich relationships typed HAS_FEATURE, what i want to do is query properties for a given array of feature keys using Filters. Follwing is code,
featureKeys is a java List here,
filter = new Filter("key", ComparisonOperator.IN, featureKeys);
filter.setRelationshipType("HAS_FEATURE");
filter.setNestedPropertyName("hasFeatures");
filter.setNestedPropertyType(Feature.class);
filters.add(filter);
SESSION.loadAll(Property.class, filters, new Pagination(pageNumber, pageSize));
The problem is i want only the properties that related to all the given features keys to be returned, but even the properties that is related to one element of the given feature key list is also returned. What do i need to do to query only the properties that are linked to all the given list elements, i can change the rich relationship to a normal relationship if needed.

How to fetch all objects AND their related objects AND filter by a related objects properties?

I tried two methods.
loadAll allows fetching of all objects AND their related objects are attached as well but does not allow me to filter by a property of a related object (I believe as I cannot work out how).
Secondly, I thought maybe this query would return all the related entities but does not.
MATCH (n:`MMLBusiness`) WITH n MATCH p=(n)-[*0..1]-(m) RETURN n
Cannot work out how to fetch all objects AND their related objects (which loadAll does) attached AND filter by a related objects properties (which loadAll does not seem to allow me to do)?
Filtering means I wish to filter the properties of the related objects, not the MMLBusiness.
For a solution I'm going to do it in two steps, first I'm going to query to fetch all ID's by normal NEO4J Query then I'm going to fetch all those objects with those ID's.

Storing object as property in Neo4j

I need to store an array of User objects inside a Tile node. Each User object contains three primitive properties; Id(a single alpha-character string) , fName and lName. This list of objects is a property of the Tile node with several other primitive properties. The entire Tile node needs to be serialized to Json, including the nested User objects.
I understand that Neo can't store complex objects as properties. I created the User as a separate node with id, fName and lName as properties, and I can get these returned via Cypher. I can also get Json output results for the parent Tile node. (In this case, Users is just a string of comma-separated alphas). But how do I get the User node output nested inside the parent node?
I have created a list of User objects (userList) by relating user objects with the string of user ids in the Tile Node via a Cypher Query. I just need to get from two separate json outputs to a single nested output.
I hope this is enough detail. I'm using Neo4j 2.1.6 and Neo4jClient. I'm also using .Net 4.0.
You could do something like this with cypher and have the cypher return a composite object.
MATCH (t:Tile)-[:CONTAINS_USER]-(u:User)
WHERE t.name =~ 'Tile.*'
WITH {name: t.name, users: collect(u) } AS tile
RETURN collect(tile) AS tiles
You shouldn't store another object as a nested property. As you correctly state, neo4j doesn't support that but even if it did, you shouldn't do it, because you should link the two with a relationship. That's the key strength of a graph database like neo4j, so you should play to that strength and use the relationships.
The server has a default JSON format that tends to output nodes as their own JSON objects. That means that practically speaking, since you're going to model this as two separate nodes with a relationship, you can't get the server by default to nest the JSON for one object underneath of the other. It won't nest the JSON that way because that's not how the data will be stored.
In this case, I'd use the REST services to fetch the JSON for each object individually, and then do the nesting yourself in your code -- your code is the only place where you'll know which property it should be nested under, and how that should be done.
In addition to these answers, note that if you don't need to involve the subfield properties in any of your queries (e.g. search for Tiles where a User.name is "X"), you can simply serialise the objects fields to a string before insertion (e.g. with JSON.stringify), and unserialise them when reading from the DB.
This is especially useful when you want to "attach" structured data to a node, but that you don't much care about this data with regards to the relations in your DB (e.g. User preferences).

Do we need to index on relationship properties to ensure that Neo4j will not search through all relationships

To clarify, let's assume that I have a relationship type: "connection." Connections has a property called: "typeOfConnection," which can take on values in the domain:
{"GroupConnection", "FriendConnection", "BlahConnect"}.
When I query, I may want to qualify connection with one of these types. While there are not many types, there will be millions of connections with each property type.
Do I need to put an index on connection.typeOfConnection in order to ensure that all connections will not be traversed?
If so, I have been unable to find a simple cypher statement to do this. I've seen some stuff in the documentation describing how to do this in Java, but I'm interacting with Neo using Py2Neo, so it would be wonderful if there was a cypher way to do this.
This is a mixed granularity property graph data model. Totally fine, but you need to replace your relationship qualifiers with intermediate nodes. To do this, replace your relationships with one type node and 2 relationships so that you can perform indexing.
Your model has a graph with a coarse-grained granularity. The opposite extreme is referred to as fine-grained granularity, which is the foundation of the RDF model. With property graph you'll need to use nodes in place of relationships that have labels applied by their type if you're going to do this kind of coarse-grained graph.
For instance, let's assume you have:
MATCH (thing1:Thing { id: 1 })-->(:Connection { type: "group" }),
(group)-->(thing2:Thing)
RETURN thing2
Then you can index on the label Connection by property type.
CREATE INDEX ON :Connection(type)
This allows you the flexibility of not typing your relationships if your application requires dynamic types of connections that prevent you from using a fine-grained granularity.
Whatever you do, don't work around your issue by dynamically generating typed relationships in your Cypher queries. This will prevent your query templates from being cached and decrease performance. Either type all your relationships or go with the intermediate node I've recommended above.

Is node reference equality in embedded neo4j guaranteed?

I am using an embedded graph database as part of a java application. Suppose that I carry out some type of cypher query, and return an ExecutionResult which contains a collection of nodes.
These nodes may be assumed to form a connected graph.
Each of these nodes has some relationships, which I can access using node.getRelationships(Direction.OUTGOING). My question is, if the target of one of these relationships already occurs in the Execution result (i.e. the relationship is part of the query template), is it guaranteed that Relationship.getEndPoint == Node X.
I suppose that what I am really asking is, when a transaction in Neo4j returns a node, does it return just the one object, and different queries will just keep returning references to that one object, or does it keep producing new objects which happen to refer to the same data point? Since Node doesn't override the equalsTo method, I have been assuming the former, but I was hoping someone could tell me.
Nodes are not reference-equals. You'll only get NodeProxy objects which are created on the fly in different operations.
But the equals()-method does id-equality so you should use that.
n1.equals(n2)
or if you keep the node id around use
n1.getId() == n2.getId()
See when you create a node neo4j internally assigns it a node-id. All the relationships you create will have reference to the start node id and end node id.
For checking do this
First create a node and save its node id by calling method node.getId()
Now create a relationship to it from another node. And call your relationship.getEndNode().getId() .
You will see the node-ids are same.
It sounds like your asking - does Neo 'out of the box' give concurrency control of database entities, like n-hibernate or entity framework does for SQL.
The answer is no! You will have to manage it yourself. If you do delelop it though, could make you a few bob

Resources