Vinelab/NeoEloquent - Realtionship to a exisiting node - neo4j

I am using Vinelab\NeoEloquent for a new project for Neo4j. I have a registration where people can supply interests (as nodes). When registering, first the user is created, then the interests are created (if they don't exist), an given a relationship of "Interested_In" from the person to the interest nodes.
Problem I am having is when the interest already exists (unique by name property) and I just want to create a relationship from the person created and the Interest node.
In my People Model I have (Since 1 person can have many interests):
public function interest(){
return $this->hasMany('App\Models\Interest','Interested_In');
}
In my create user function in my repository I have a section where it searches the Interests and returns one if one exists. Problem is I don't know how to then create the realtionship from People to Interest. I try to save it as
$interests = explode(',',$input['tags']);
$int = new NeoInterestRepository();
foreach($interests as $interest){
$existing = $int->find($interest);
if(count($existing)){
$person->interest()->save($existing);
}else{
$my_interest = $int->create($interest);
$person->interest()->save($my_interest);
}
}
But I get 'Argument 1 passed to Vinelab\NeoEloquent\Eloquent\Relations\HasOneOrMany::save() must be an instance of Illuminate\Database\Eloquent\Model, instance of Illuminate\Database\Eloquent\Collection given'
I see the associate() function but its only for BelongsTo which doesn't seem to apply.
Any ideas?

Related

Spring data for neo4j generating dynamic relationships between entities

I just started reading and playing with graph db and specifically Neo4j.
However I didn't encounter a solution for a use case that seems to me very common. Assume I have User object in my system and I want to maintain the relationships between users.
Examples:
User1 -> User2 - relationship sibling
UserX -> UserY - relationship parent
UserY -> UserX - relationship child
UserX -> UserZ - relationship teacher
I would like to store the relationship (the edge between the nodes) dynamically and not creating an entity with all possible relationships entities with annotation #Relationship.
Later, I would like to get a user and all his connections, but in run-time to figure out what is the type of the relationship.
Is this possible with spring data? or maybe it is not possible at all using Neo4j?
I will appreciate if you can point me to some reading for a solution to my problem.
Thank you.
It seems that you are only interested in the type of relationship after you would query for all, right?
You could use a #RelationshipEntity and add a property to it to define its type.
#RelationshipEntity(type = "USER_RELATION")
public class UserRelation {
//... #StartNode/#EndNode/#Id
private String type; // Here goes sibling, parent, etc.
}
And in your User entity you would just define one relationship.
#Entity
public class User {
// ... id, etc.
#Relationship(type = "USER_RELATION")
private List<UserRelation> userRelations;
}
This would always query every outgoing connection to another user.

GORM one to one relationship while keeping existing entries

After going over GORM's documentation, I've figured out how to create one-to-one relationships between objects. However, I haven't figured out how to go about enabling my desired relationship. The relationship I'm trying to create acts as a one-to-one, but keeps previous row entries for historical purposes.
For example, a Car can have multiple owners throughout its lifetime. If I have Car and Owner domain objects, how can I specify that the most recent entry in the Owners table for a given Car ID is the correct one?
There are lots of different ways to model this. IMO, one of the most flexible approaches is:
class User {
String name
static hasMany = [ownerships: Ownership]
}
class Car {
String name
static hasMany = [ownerships: Ownership]
}
class Ownership {
Date start
Date end
static belongsTo = [owner: User, car: Car]
}
For example, when Ann sells her car to Bob, we set the end-time of Ann's Ownership record to the time of sale and save a new Ownership record for Bob with the start-time set to the time of sale.
If getting the current owner of a car is an operation we frequently need to perform, we could add a currentOwner method to Car
class Car {
String name
static hasMany = [ownerships: Ownership]
Ownership currentOwner() {
// depending on how this method is used, you might want to
// return the User instead of the Ownership
Ownership.findByEndIsNullAndCar(this)
}
}

Don't delete object of destination if it is in another Source in Coredata

I have a many to many relationship where entity are Employee and Department. Everything is going good but when i am trying to learn the relationship delete rules,i couldnot find out the right way.
I want to remove all the employee of the department if Entity Department gets deleted.But not those employee who are in another deparment.
Cascade Delete the objects at the destination of the relationship. For
example, if you delete a department, fire all the employees in that
department at the same time.
But i dont want to remove the employee if they are already in another department.One teacher teaching Swiftmay be in many departments "Computer","Electrical","Civil".How can i acheive that..Tried to use cascade but that removes all the Employees which i have set destination as below:
EDIT: Tried using nullify but deleting Source causes the deletion of all related Destination. However, deleting any single one Source simply causes Destination to forget about that particular Source.I gues,I need something intermediate nullify and cascade?
The following relationships will do what you want I think (I don't have the ability to test the answer here, but don't have rights to just leave a comment so you get the suggestion as an answer)
Employee -> Department Deny (can't fire an employee that is still assigned to a department).
Department -> Employee Cascade (fire all employees you can fire when the department is deleted, ie no longer has a department).
But it seems more reasonable to me set Department -> Employee to Nullify, and then make a separate scan for unassigned employees to fire outside the delete department code. This would also support general maintenance checks for employees that have had all their assignments removed.
In the case of mine i should not set the delete relationship to Cascade.But instead make both delete rule to nullify.And Check as in
class Departments: NSManagedObject {
// Insert code here to add functionality to your managed object subclass
override func prepareForDeletion() {
for teacher in self.teachers!{
if let tempTeach = teacher as? Teachers{
if tempTeach.departments?.count == 1{
self.managedObjectContext?.deleteObject(tempTeach)
}else{
print("this teacher is assigned to another department also so dont delete it")
}
}
}
}
}

Dynamics CRM Merge Two Contacts with C# code, modified example from SDK

I've been trying to get the Merge example in Dynamics CRM 2011 SDK to work.
http://msdn.microsoft.com/en-us/library/hh547408.aspx
I've modified it a bit. I've created two Contacts instead of Accounts (although some variable names in the code might suggest otherwise. For example _account1Id is in fact a GUID for contact1.)
The first Contact record has name, surname and telephone fields filled.
The second Contact record has name, surname and email fields filled.
The part where merge occurs is below. The original code can bee seen from the link at the top.
When I run the example with following modifications, the e-mail address doesn't get merged into the new contact record. What I get is one merged Contact with the values from one of the records, with address data added, but no e-mail. I thought this was supposed to fill empty fields of the primary record with the non-empty fields from the second record.
Being very new to Ms Dynamics CRM, I couldn't understand the reason after much googling and debugging. I'll be glad if someone can give me some feedback about what the problem might be.
Thanks in advance.
_serviceProxy.EnableProxyTypes();
CreateRequiredRecords(); // created two contacts with same name, surname. first record has telephone1 filled, second record has emailaddress filled.
EntityReference target = new EntityReference();
target.Id = _account1Id;
target.LogicalName = Contact.EntityLogicalName;
MergeRequest merge = new MergeRequest();
merge.SubordinateId = _account2Id;
merge.Target = target;
merge.PerformParentingChecks = false;
Contact updateContent = new Contact();
updateContent.Address1_Line1 = "test";
merge.UpdateContent = updateContent;
MergeResponse merged = (MergeResponse)_serviceProxy.Execute(merge);
Contact mergeeAccount =
(Contact)_serviceProxy.Retrieve(Contact.EntityLogicalName,
_account2Id, new ColumnSet(allColumns: true));
if (mergeeAccount.Merged == true)
{
Contact mergedAccount =
(Contact)_serviceProxy.Retrieve(Contact.EntityLogicalName,
_account1Id, new ColumnSet(allColumns: true));
}
That behaviour would be as expected - the Merge will move over child records for you from the subordinate to the master (so potentially opportunities, addresses etc.) but not try to workout which fields you want copied over. The reasoning (I would guess) is the potential business logic implications are endless - do you want to copy over emails? what if all email fields are filled? what about custom fields? And lots of other cases I'm sure everyone can think of.
Edited:
To workaround this, there is a property on the MergeRequest class called UpdateContent. If you update fields on this property, the values will be merged into the parent record.
You can actually see this in the link you has posted:
// Create another account to hold new data to merge into the entity.
// If you use the subordinate account object, its data will be merged.
Account updateContent = new Account();
updateContent.Address1_Line1 = "test";

Getting the ID of a one-to-many loaded object without another trip to the DB with GORM

I have to GORM domains, A & B, that relate to database tables. A has a one-to-many relationship with B. Because of this, the classes look similar to:
class A {
B b
Long id
}
class B {
Long id
}
When I retrieve an instance of A the ID of the corresponding instance of B is retrieved from the database. However, when I attempt to access that ID via something like:
A a = A.get(11)
Long bid = a.b.id
the whole object is loaded from the database. In some cases I only want the ID of B (which has already been retrieved) and do not want to load the whole instance from the database. Is there a way to get the ID from B without going back and fetching the whole object.
NOTE: I know that it is doing an extra fetch on the line with a.b.id above because I can see the SQL being generated since I turned on the loggingSql option in my DataSource file.
Instead of:
Long bid = a.b.id
use:
Long bid = a.bId

Resources