Spring Data Neo4j - #RelationshipType issues - neo4j

I'm having difficulties retrieving relationships when the relationship type is annotated with a #RelationshipType field.
The relationships look correct in Neoclipse, but I'm retrieving no results in my application.
The code that doesn't work is (simplified):
#NodeEntity
public abstract class Entity {
#RelatedToVia
private Collection<Relationship> relationships;
public Relationship relatedTo(Entity entity, String type) {
Relationship relationship = new Relationship(type, this, entity);
relationships.add(relationship);
return relationship;
}
...
}
and:
#RelationshipEntity
public class Relationship {
#RelationshipType
private String type;
...
}
The code that does work is:
#RelationshipEntity(type = "something")
public class Relationship {
...
}
However, this doesn't suit my use case (I have a bunch of different Relationship types between arbitrary combinations of Entity instances.
The full test code is below. Agency and Item are both subclasses of Entity.
// Create first entity
Agency arnz = agencyRepository.save(new Agency());
arnz.setCode("ARNZ");
agencyRepository.save(arnz);
// Create second entity
Item r123 = itemRepository.save(new Item());
r123.setCode("R123");
// Create parent/child relationship between entities
r123.relatedTo(arnz, EntityRelationshipType.PARENT);
itemRepository.save(r123);
// Retrieve entity from database
Entity entity = itemRepository.findByCode("R123");
// Verify that relationship is present
assertThat(entity.getRelationships().iterator().hasNext(), is(true));
The final line is where the test is failing. Any clues?
M
PS. I'm a rank amateur with Neo4j and just happened to find #RelationshipType, so I may well be doing something laughably wrong. I hope so!

Sorry to disappoint you, but during the retrieval the code right now doesn't look for the type class but rather for the type from #RelatedToVia or #RelationshipEntity or the field name relationships as relationship-type. But you're making a valid point, can you please raise in issue in JIRA?
Did you look into template.getRelationshipsBetween ?
Why don't you create individual classes for your relationships? What is the use-case for this approach?

Related

how to get the relationship from Collection of relationships between two nodes using springdata Neo4j with GraphRepository

I have two entities like Users and Accounts. User node related to Account node
with any of the 20 relationships. Please find the sample image design attached
i need to search accounts for corresponding users using any of the 20 relationships. i used the cypher query for retriving user details and the accounts.. Relationship between the two entity will be either any one of the 20 relationships . so i can't annotate the #RelationshipEntity type value. Please find the code for example
User.java
public class User
{
private Long id;
String fulltextsearch;
String user_id;
String status;
#Relationship(type = "perm")
List<Acronym> acronym;
.....
...
}
Acronym.java
#JsonIdentityInfo(generator=JSOGGenerator.class)
#RelationshipEntity
public class Acronym {
#GraphId
Long id;
String acronym;
#StartNode
private User user;
#EndNode
private Account account;
....
....
}
Userrepository.java
#RepositoryRestResource(collectionResourceRel = "User", path = "User")
public interface Userrepository extends GraphRepository<User> {
User findByLogin(#Param("login") String login);
#Query("MATCH p=(user:User)-[r*0..1]->(account) WHERE user.login =~('(?i).*'+{Login}+'.*') RETURN p")
Collection<User> findByloginContaining(#Param("login") String login);
}
i tried creating objects for each relationship (ie 20 relationship object.). i'm not sure if that correct way to get the value.
Could anyone please help me to know to fetch the relationships against the account? it always retrives as null.
Thanks in advance.
The OGM/SDN 4 does not support unknown relationship types. The type of relationship must be specified on a #RelationshipEntity.
One way of doing this is as you said, create a #RelationshipEntity per type, but this also means that you must specify 20 such relationships in your User class, because the relationship type differs (even though the start/end nodes are the same). This may not be ideal, and difficult to manage.
If your application primarily works with dynamic relationship types, the OGM may not be a good fit.
NOTE: Mapping custom query results to entities is only supported in OGM 2.x / SDN 4.1. You cannot return a path, just the entities that make up the path such as nodes and rels.

Polymorphic Expand Breeze Navigation Properties

I have something like this:
public class Person {
string Name;
}
public class Customer : Person {
List<Order> orders;
}
public class MyReference {
Person aPerson;
}
public class Me {
MyReference myRef;
}
Now in my Metamodel I have specified a baseType for Customer. And I think my metamodel is right. The only problem is, that when I want to execute a query like the following:
breeze.EntityQuery.from('Me').expand('myRef, myRef.aPerson, myRef.aPerson.orders')
I get an error, that "orders" is not allowed on the EntityType "Person". Of course as it's the base-class. I would like it to be polymorphic and if the Person is really of Type "Customer" it should expand orders and if not, well then it can be empty or not defined or not even existent on the object.
Is this somehow possible? Would I need some kind of "toType" to cast inside the Query?
The base class, Person, does not have an Orders property. Therefore, .NET (EF) on the server won't let you ask for Person.Orders. That's not how polymorphism works in EF and there isn't anything Breeze can do to change that.
You'll need a different approach I'm afraid.
FWIW, that isn't how polymorphism works in Breeze either.

How to make a "deep" transformation in Grails withCriteria contains projection?

I am using Grails 2.2.4 to build a web application, and now I am having a complex problem with Grails withCriteria operation. I have 3 classes as below:
class Person {
int id
String name
Set<Car> cars = [] // One-to-many relationship
Company currentCompany // One-to-one relationship
}
class Car {
int id
String manufacturer
String brand
double price
Person owner
}
class Company {
int id
String name
Set<Person> employees = []
}
And now I want to query data from Person as root class along with associated data like this:
List result = Person.withCriteria {
projections {
property('id')
property('name')
createAlias('cars', 'c', CriteriaSpecification.LEFT_JOIN)
property('c.brand')
createAlias('currentCompany', 'com', CriteriaSpecification.LEFT_JOIN)
property('com.name')
}
lt('id', 10L)
resultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY)
}
And the problem is, I don't know how to transform deeply the result data to a List of persons to make sure every single element contains its data as the class structure. I tried many methods like
resultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY)
resultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP)
resultTransformer(CriteriaSpecification.aliasToBean(Person.class))
but nothing worked as I expected.
Does Grails 2.2.4 support this? If yes so what is the correct syntax?
Thank you so much.
Actually, after researching many articles, Grails documentation and even its source code, I think the best way to do this is implementing a custom transformer for my own purpose. The most difficult thing here is how to transform data to association objects and gather them to collection inside the root entity. And I have created one here:
http://www.mycodestock.com/code/10333/
Hope it helps you guys who may need something like mine.

How to define association relationship in grails

UPDATED
I have a domain classes as below
class Training{
// has one createdBy object references User domain and
// has one course object references Course domain
// has One Trainer1 and Trainer2 objects refernces Trainer Object.
}
class Trainer{
String name
//can have many trainings.
//If Trainer gets deleted, the trainings of him must be deleted
}
Class User{
String name
// can have many trainings.
}
class Course{
String name
//If Course gets deleted, Trainings of this course must be deleted
// can have many trainings.
}
I have got a training create page, Where I have to populate already saved Course, User, Trainer1 and Trainer2. I am not saving them while Creating the training.
So, How to specify the relationship in grails
You did not put any effort to searching answer for yourslef. There are plenty basic examples and blog posts how to map relations in Grails. You should start with Grails documentation of GORM - Grails' object relational mapping. You can find it here.
I see some minor flaws in yout initial design: ie why should training be deleted if user is deleted when trainings will obviously tie with many users. Can training exists without trainers or vice versa ?
I would start with something like this:
Class Training {
static hasMany = [users: User, trainers: Trainer]
static belongsTo = Course
}
Class Trainer {
String name
}
Class User {
String name
}
Class Course {
String name
static hasMany = [trainings: Training]
}
EDIT: I have to agree with Tomasz, you have jumped here too early without searching for answers yourself. Grails.org has good documentation about GORM with examples too.

Legacy mapping in Grails/GORM: One domain class and two tables in a 1:N-relationship

Let's say I have two tables employee and salary with a 1:N relationship (one salary can be associated with many employees).
In plain SQL the tables would be joined with:
SELECT e.id, e.name, s.salary FROM employee e, salary s WHERE s.id = e.salary_id AND e.id = 12345;
Assuming the following GORM-powered domain class how do I map the legacy database structure to the class?
class Employee {
String name
int salary
}
Clarification #1: I want only one domain class containing data from both tables. Adding another class is hence not an option.
Clarification #2: The question I'm trying to find an answer to is simply "how do I map two tables to one class using Grails/GORM"? If you believe that it is impossible to do so, then please state that clearly in your answer rather than trying to restate the question.
IMO it is not possible with plain Grails/GORM to join multiple tables and map them to one Domain class. As a workaround you could use a legacy XML hibernate mapping and leverage the join feature to achieve your desired goal. Of course you would loose a lot of the GORM goodies.
Your SQL example indicates there are two tables, Employee and Salary. This should also be reflected in your classes. So instead of one, you need two classes. The GORM mapping would then look like this.
class Employee {
String name
Salary salary
}
class Salary {
static hasMany = [ employees : Employee ]
int salary
}
See http://www.grails.org/GORM+-+Defining+relationships
You could, instead of having salary and name as properties, have them as get* methods that actually run a query on both these tables.
granted, that isnt the grails way, and its strongly recommended that you do follow the grails way.
I don't fully understand the limitation on not being able to add another class if there are 2 tables in the database, but if you're looking to have a unified interface, would it work to delegate the methods to the Salary class?
Something like:
class Salary {
int amount
}
class Employee {
Salary _salary
String name
String toString() { name }
public Integer getSalary() {
return _salary?.amount
}
public void setSalary(Integer amount) {
// not quite sure of your business logic here, this is a guess
_salary = Salary.findByAmount(amount)
if (!_salary) {
_salary = new Salary(amount: amount)
_salary.save()
}
}
}
def e = new Employee(name:"willy loman", salary: 100)
e.save()
assert e.salary == 100
It's also possible that you might be able to make what you're asking for work with a custom hibernate mapping file, but I'm not familiar enough with contorting hibernate in that manner to say for sure.
See the Custom User Type section of this page.

Resources