Problem/Motivation
Entity reference field items are not removed when the referenced entity is deleted.
E.g.
- Create taxonomy term with tid 123 "trees".
- Create node "pine" with nid 456 tagged with "trees".
- Delete the "trees" term. Nid 456 will still be related to tid 123 even though there is no longer such a term.
Mostly this isn't a problem. Some examples where it can cause problems:
- Search facets with an incorrect count of results.
- Cryptic error messages when editing entities that contain collapsed Paragraphs.
- Null fields in GraphQL results (which is invalid GraphQL).
- Acquia's Cohesion product (see "Why is my Cohesion layout table so large" which points to this issue)
What can I do until a patch has been created?
Why doesn't a fix for this already exist in core?
- There are scenarios where dangling references shouldn't be automatically cleaned up (if you need a human, or some other system to take action).
- It's a performance challenge. There may be tens of thousands (or more) dangling references to clean up.
Proposed resolution
In interactive scenarios - like the entity delete confirm form - ask the editor if they want to delete the orphaned references:
- immediately (default)
- in the background or
- don't remove the references at all (not recommended)
In a non-interactive environment (PHP API, REST API) always use the second option.
Remaining tasks
User interface changes
New radio group on the entity delete confirmation form (and bulk operations confirm form too?).
API changes
TBD
Data model changes
None
Comments
Comment #2
blazey commentedComment #3
blazey commentedComment #4
blazey commentedComment #7
wim leersComment #8
hchonov+1 on such a feature.
The option should be available only if enabled by a setting.
However the user should be aware what exactly is being deleted and we would need to preset a list (probably with checkboxes to allow opting out of some deletions).
Please note that even the owner of the entity is behind an entity reference field. Therefore we need to enable this per field - this is something we do in one of our projects already.
However the list might get long in cases of long and nested list of references - for example entity type A references 10 entities of entity type B, which references another 20 entities of entity type C and so on ...
Comment #11
chi commentedIt's more like a bug. Isn't it?
Comment #12
dino.amino commentedYep. A real hot mess. I don't think most people realize how out of control it becomes. We certainly didn't when we started our Drupal project.
3 years, 400 authors and 8,000 nodes later we have a crisis on our hands.
If we only knew then what we know now ... thanks Acquia /s
Comment #13
mrpauldriver commented#12 Yes I have just become aware of this 'hot mess'. I worry this could lead to problems down the road.
Comment #14
dalinReading through the comment history, it looks like a couple people are confused about this is about.
Note that we're not talking about going the other direction (If you delete a entity, also delete the entities that are referenced by this entity).
I'm cleaning up the description to clarify.
Comment #15
kreatil commented+1
A possible solution would be to scan all field entries of the type "entity reference" (How to select by field type?). If a field contains the entity id of the entity (to be) deleted, the entry is removed.
Comment #16
bojan.m commentedI also had the same problem with this thing but only with referenced custom entities. My solution was that, like kreatIL said, to go through all entities which has entity reference field and update them. This is my solution and it works fine for me. I am not sure why we do not have something like this already in core because it is really problematic thing when you are working (create/update/delete) entities programmatically.
Comment #17
dalin@bojan.m
I am not sure why we do not have something like this already in core
I updated the issue description to describe why:
Comment #18
mdupontStill relevant for 9.x :-)
Also there is already a basic example of reference cleanup in core in node_user_predelete() which deletes nodes which have as author the user being deleted.
Comment #19
bojan.m commented@dalin
Well, I do not see this performance challenge as big issue because it can be managed by queues like Revisions that are no longer used.
Something like "Entity Reference Revisions Orphan Purger" from Entity Reference Revisions module where you do not update all entities in one request but you put them in queue.
Comment #20
dalin@bojan.m
I agree, I'm just stating why it doesn't already exist.
Comment #21
bojan.m commentedWe had some free time to create module that will solve this problem.
Entity reference purger
Feel free to test it and use it.. if you have something on your mind please write us issue.
Thanks.
Comment #24
taggartj commentedYes in my case it was JSON API having a node resource with a (Required) dynamic_entity_reference field of type node
if you delete the referenced node = fire and brimstone and serious cryptic error.
leading to you doubting core , JSON API and your own sanity
Comment #26
dalinComment #27
dalinComment #29
xurizaemonAcquia docs link to this issue as the cause of surprisingly large DB tables belonging to their Cohesion system.. On a site I looked at there were 63K nodes, 75K node revisions, and the table
cohesion_layout_field_revisionwas 630MB in size. (This was larger than the entire Drupal codebase and the remainder of the site DB put together.)Adding Acquia's Cohesion tables to the "examples of this problem" list in ID.
Comment #30
joachim commentedI made a contrib module that takes care of deleting references: https://www.drupal.org/project/entity_reference_delete
Comment #31
anybodyIn addition to #30:
I agree, references need a functionality like databases have to track references and remove orphans and it should be in core. Still I understand the complexities ;)
Comment #32
kreatil commented#31: +1
We have been using Entity Reference Purger in production for over a year. The module addresses exactly the issue described in the original post. In our usecase, the number of references to be deleted is typically in the triple digits, without any significant performance issues.