Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update relations via set of ids or something like that #64

Open
mrakolice opened this issue Jan 30, 2020 · 3 comments
Open

Update relations via set of ids or something like that #64

mrakolice opened this issue Jan 30, 2020 · 3 comments
Labels
type:question Further information is requested

Comments

@mrakolice
Copy link
Contributor

I need to update HasMany and ManyToMany relations via set of ids, instead of loading entities that exists in database.

For example:

Child table

Id Parent id field
1 1 1
2 1 2
3 null 5
$parent->children->sync([1,3]);
$parent->save();

Child table

Id Parent id field
1 1 1
2 null 2
3 1 5

ORM should generate 2 update queries for nullable hasMany relations and 1 update and 1 delete query for not nullable hasMany relations and ManyToMany relations.

UPDATE child SET parent_id = null
WHERE id IN (SELECT unnest(?) EXCEPT
SELECT child.id FROM child WHERE child.parent_id=?);

DELETE FROM child 
WHERE id IN (SELECT unnest(?) EXCEPT
SELECT child.id FROM child WHERE child.parent_id=?);

UPDATE child SET parent_id = ?
WHERE child.id IN ?;
@wolfy-j
Copy link
Contributor

wolfy-j commented Jan 30, 2020

This is doable since the relation controls chain of persist commands, need to think about an API to avoid fetching... Let me think about it.

@alexndr-novikov
Copy link
Contributor

@mrakolice technically it's possible when using Cycle, but are you sure it's a good idea to use Data mapper orm like this?
It will give too much control over persistence layer to you application layer if you modify database relations via ids
It's more usual to operate with relations as collection of objects (or inner object for HasOne case)

@mrakolice
Copy link
Contributor Author

$parent = [
    'field1' => 'value'
    'children' => 
    [
         ['id' => 1],
         ['id' => 2],
         ['id' => 3],
    ]

];

All child entities exists in database, but child entity with id=3 not in this particular parent.

So, when I going to do smth like this:

$parent = $orm->getRepository(Parent::class)->load('children');

I can use only entities with [1,2] id;
And this is what I can do with collection of objects:

$childIds = $parent->children->map(); // or load entities only with id via load method above

$entitiesToAdd = diff($ids, $childIds);

foreach ($orm->getRepository(Child::class)->where('id', 'in', $entitiesToAdd) as $child){
    $parent->children->add($child);
}

$transaction->persist($parent);
$transaction->run();

This approach a bit sophisticated for me and I need to fetch entities to add from database, but this is just diff operation between two arrays, no matter - in php layer or sql layer.

If I do something like this:

$entities = $orm->getRepository(Child::class)->where('id', 'in', $entitiesToAdd);
$transaction = new Transaction();

foreach ($entities as $child){
    $child->parent = $parent;
    $transaction->persist($child);
}
$transaction->run();

This will be produce many update queries on sql layer.

I can use UpdateQueryBuilder (and I've solved this problem exactly via QueryBuilder), but I think, that this problem very viable for many developers, that using Cycle ORM or any another ORM. =)

@wolfy-j wolfy-j added the type:question Further information is requested label Feb 1, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type:question Further information is requested
Projects
Status: Backlog
Development

No branches or pull requests

3 participants