Neo4j OGM Filter query against array - neo4j

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.

Related

Neo4j Cypher query to show entire graph, including relationship properties?

I'm building a Neo4J system just do to visualization in the Neo4J browser. I build the various nodes and relationships and I can visualize the database by running match (n) return n. The problem is that the resulting display shows the relationship names but not their associated properties. Can anyone tell me the cypher query to show the entire database including relationship properties? Thanks.
The neo4j browser does not support visualizing all properties (for nodes or relationships) at the same time. Such a capability would generally result in a very congested and unusable visualization, especially since the browser would also have to display the property names.
You can, however, opt to show the value of a single property per node label or or relationship type as its caption. You can do that manually, or you can edit the GRASS file to set all of the captions at once. As an example of how to set relationship captions in the GRASS file, the following entry in that file would specify that all BAR relationships should show their foo property:
relationship.BAR {
caption: '{foo}';
}

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.

spring data neo4j 3.0.0 - why two labels set by default

I need to write batch importing utility for my Neo4j database but I don't want to lose the repository feature of SDN. To achieve this goal I want to insert such nodes that can be still queried using auto generated repository methods.
I inserted some nodes to my database and I looked at their properties and labels to see how they are set and I noticed that SDN inserted nodes have two labels. For example nodes representing class SomeClass have labels: ["_SomeClass", "SomeClass"]. My question is: why set two, almost identical labels for each node?
Oh that's actually simple. We somehow have to note if the current node is of type SomeClass, which we do by prepending the "_". As there are labels added for each super-type you need to differentiate what the actual type of the node in Spring Data Neo4j is.
So you could have: _Developer, Developer, Employee, Person for a class hierarchy from Person down to Developer. And then there could be additional labels for interfaces.
When you now do: DeveloperRepository.findAll() then you only want those with _Developer back, not ones that derived from Developer.

neo4j registering object into field

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.

Resources