Delete node references for some content types only Unless there's a method I'm unaware of, node references are not related to their node's content type. I need to delete referenced nodes when the target ids are not of a certain content type. Here's my code so far.

// Get My content type nodes.
$nids = \Drupal::entityQuery('node')
  -&gt;condition('type', 'my_content_type')
  -&gt;execute();
/** @var \Drupal\node\NodeInterface[] $nodes */
$nodes = Node::loadMultiple($nids);
foreach ($nodes as $node) {
  // Select the related nodes from each node.
  $result = \Drupal::database()-&gt;select('node__my_reference_field', 'n')
    -&gt;fields('n')
    -&gt;condition('entity_id', $node-&gt;id())
    -&gt;execute();

  // Determine what content type the related node is.
  while ($record = $result-&gt;fetchAssoc()) {
    $query = \Drupal::database()-&gt;select('node_field_data', 'nfd');
    $query-&gt;fields('nfd', ['type']);
    $query-&gt;condition('nid', $record['my_reference_field_target_id']);
    $type = $query-&gt;execute()-&gt;fetchField();

    if ($type != 'content_type_one' || $type != 'content_type_two') {
      \Drupal::database()-&gt;delete('node__my_reference_field')
        -&gt;condition('entity_id', $node-&gt;id())
        -&gt;condition('my_reference_field_target_id', $record['my_reference_field_target_id'])
        -&gt;execute();
    }
  }
}


If this line 

if ($type != 'content_type_one' || $type != 'content_type_two') {


were 

if ($type == 'content_type_one' || $type == 'content_type_two') { 


the related nodes of content_type_one and content_type_two are deleted. Using != removes all the related nodes on the node. I only want to remove the related nodes that are not of content_type_one and content_type_two.

What am I missing?



@Jaypan here's the exact code that takes nine minutes to run.

function my_module_update_8008() {
  // Get the nodes.
  $nids = \Drupal::entityQuery('node')
    -&gt;condition('type', 'my_type')
    -&gt;execute();

  /** @var \Drupal\node\NodeInterface[] $nodes */
  $nodes = Node::loadMultiple($nids);

  foreach ($nodes as $node) {
    // Delete references on the nodes that are not news or story.
    foreach ($node-&gt;get('field_entity_reference')-&gt;referencedEntities() as $entity) {
      drush_print($node-&gt;id());
      if (!in_array($entity-&gt;bundle(), ['news', 'story'])) {
        $entity-&gt;delete();
      }
    }
  }
}


drush_print() is for debugging purposes. During the run of this code, a $node->id() prints every 1 or 2 seconds. As you well know, to run an update_N hook from the command line, use

drush php-eval 'module_load_include('install', 'my_module'); my_module_update_8008();';


Anyway, it's 160 nodes x ~20 node references for each node. So the drush_print() helps me understand where the time is going.

Thanks for your help. I didn't mean to sound ungrateful. I think referencedEntities() and $entity-&gt;bundle() and the like are great, but I find them too slow. Once I have the field table populated with only the records I need, drush cr gets the referenced nodes to print in the text fields on the admin. I'll post my query code when I get it working again.

Btw, it's getStorage() not loadStorage() with entityTypeManager(). Thanks again.
Your code can be made more concise using Drupal APIs. It's rare that DB queries are required in Drupal 8, as the system generally has APIs that handle it for you. Here's how I'd do what you're trying to do. I think the key you were looking for is the line with in_array().

// Load all 'some_content_type' nodes.
$properties = [
  'type' =&gt; 'some_content_type',
];
$nodes = \Drupal::entityTypeManager()-&gt;loadStorage('node')-&gt;loadByProperties($properties);

foreach ($nodes as $node) {
  // Loop through the entities referenced by the field.
  foreach ($node-&gt;get('my_reference_field')-&gt;referencedEntities() as $entity) {
    // Only act if the entity is not one of the given types.
    if (!in_array($entity-&gt;bundle(), ['type_1', 'type_2'])) {
      // Delete the entity.
      $entity-&gt;delete();
    }
  }
}