Ausschließen von leeren (Null-) Feldern bei Verwendung der EntityFieldQuery-Abfragebedingung

31

Ist es möglich, alle Entitäten auszuwählen, deren xyz-Feld leer ist?

Ich habe so etwas ausprobiert:

->fieldCondition('field_name', 'value', NULL, 'IS NOT NULL');

Dies scheint jedoch nicht zu funktionieren.

Irgendwelche Ideen?

David Barratt
quelle

Antworten:

19

Wenn Sie auf der Seite mit der Dokumentation zu den Feldbedingungen nachsehen , wird die folgende Warnung angezeigt :

Beachten Sie, dass Entitäten mit leeren Feldwerten bei Verwendung dieser Methode von den EntityFieldQuery-Ergebnissen ausgeschlossen werden.

Das Überprüfen, ob ein Feld vorhanden ist oder nicht, wurde zu entityFieldQuery in Drupal 8 hinzugefügt, wird jedoch leider nicht zu Drupal 7 zurückportiert .

Es gibt verschiedene Methoden, um dies zu erreichen:

  1. Unter Verwendung eines Tags und von hook_query_TAG_alter, wie von @Clive erwähnt, finden Sie in Kommentar 4 zum Drupal-Problem ein Beispiel.
  2. Fragen Sie zuerst alle Nicht-NULL-Einträge ab, und fragen Sie dann alle Einträge mit Ausnahme der vorherigen ab, wie in der Antwort von @ seddonym und in Kommentar 5 zum Drupal-Problem beschrieben .
  3. Sie können in Ihrer Abfrage schreiben Select Rathen als EntityfieldQuery als solche:

_

$q = db_select('node', 'n');
$q->fields('n', array('type'))
  ->condition('n.type', 'my_node_type', '=')
  ->addJoin('LEFT', 'field_data_field_my_field', 'f', 'f.entity_id = n.nid');
$q->isNull('f.value');
$r = $q->execute();
Alice Heaton
quelle
15

Sie können verwenden != NULL, aber Sie können = NULLaus irgendeinem Grund nicht verwenden .

Dies ist meine Problemumgehung.

  //Get all the entities that DO have values
  $query = new EntityFieldQuery();
  $query->entityCondition('entity_type', 'MY_TYPE')
    ->fieldCondition('field_MY_FIELD', 'value', 'NULL', '!=');
  $result = $query->execute();

  if (is_array(@$result['registration'])) {
    //Now get all the other entities, that aren't in the list you just retrieved
    $query = new EntityFieldQuery();
    $query->entityCondition('entity_type', 'MY_TYPE')
      ->entityCondition('entity_id', array_keys($result['MY_TYPE']), 'NOT IN');
    $result_two = $query->execute(); 
  }
Seddonym
quelle
10

Entsprechend der Dokumentation können Sie null und isnull verwenden; Es hat nur eine bestimmte Art, es zu schreiben.

$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
  ->entityCondition('bundle', 'article')
  ->propertyCondition('status', 1)
  ->fieldCondition('field_news_types', 'value', 'spotlight', '=')
  ->fieldCondition('field_photo', 'fid', 'NULL', '!=')
  ->fieldCondition('field_faculty_tag', 'tid', $value)
  ->fieldCondition('field_news_publishdate', 'value', $year. '%', 'like')
  ->range(0, 10)
  ->addMetaData('account', user_load(1)); // run the query as user 1

$result = $query->execute();

if (isset($result['node'])) {
  $news_items_nids = array_keys($result['node']);
  $news_items = entity_load('node', $news_items_nids);
}
giorgio79
quelle
9

Die kurze Antwort lautet: Direkt, nein, das können Sie nicht (siehe EntityFieldQuery unterstützt isNull oder isNotNull nicht ). Wenn ich mich recht erinnere, ist dies ein Nebeneffekt der Tatsache, dass EntityFieldQuerynur INNER JOINs zum Verknüpfen von Tabellen verwendet wird.

Es gibt jedoch eine Problemumgehung, bei der hook_query_TAG_alter()ein Tag verwendet und hinzugefügt wird. EntityFieldQueryIm letzten Kommentar auf der Seite, auf die ich oben verlinkt habe, finden Sie ein Beispiel.

Clive
quelle
5

In Drupal 7 überprüfen Sie bitte die folgende hier vorgeschlagene Problemumgehung :

Registrieren Sie das Tag, um die Abfrageinstanz zu ändern:

<?php
/**
 * Implements hook_query_TAG_alter()
 */
function MYMODULE_query_node_is_not_tagged_alter(QueryAlterableInterface $query) {
  $query->leftJoin('field_data_field_tags', 'o', 'node.nid = o.entity_id AND o.entity_type = :entity_type');
  $query->isNull('o.field_tags_tid');
}
?>

Anmerkung: Diese Abfrage-Tag-Änderung funktioniert nur für den Entitätstyp "Knoten". Verwechseln Sie "field_tags" nicht mit dem Vokabular "Tags", es kann sich auch um eine andere Kategorie handeln.

Rufen Sie mit EntityFieldQuery alle Knoten ab, die noch nicht markiert wurden. Schauen Sie sich die Methode addTag () an:

<?php
$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
  ->entityCondition('bundle', 'news')
  ->addTag('node_is_not_tagged')
  ->propertyCondition('status', 1);
$result = $query->execute();
?>

Anderes Beispiel:

  $result = $query
    ->entityCondition('entity_type', 'node')
    ->propertyCondition('type', 'my_content_type')
    ->fieldCondition('field_mine_one', 'value', '', '<>')
    ->fieldCondition('field_mine_two', 'value', '', '<>')
    ->addTag('my_custom_tag')
    ->deleted(FALSE)
    ->propertyOrderBy('changed', 'DESC')
    ->range(0, $my_range_value)
    ->execute();

Dann habe ich hook_query_TAG_alterdie Tatsache genutzt, my_custom_tagdie nur von mir festgelegt wurde:

/**
 * Implements hook_query_TAG_alter()
 */
function MYMODULE_query_TAG_alter(QueryAlterableInterface $query) {
  $query->leftJoin('field_data_field_other', 'o', 'node.nid = o.entity_id');
  $query->isNull('o.field_other_value');
}

Ein anderes Beispiel:

<?php
  //Get all the entities that DO have values
  $query = new EntityFieldQuery();
  $query->entityCondition('entity_type', 'MY_TYPE')
    ->fieldCondition('field_MY_FIELD', 'value', 'NULL', '!=');
  $result = $query->execute();

  if (is_array(@$result['registration'])) {
    //Now get all the other entities, that aren't in the list you just retrieved 
    $query = new EntityFieldQuery();
    $query->entityCondition('entity_type', 'MY_TYPE')
      ->entityCondition('entity_id', array_keys($result['MY_TYPE']), 'NOT IN');
    $result_two = $query->execute();  
  }
?>

Vollständigeres Beispiel, in dem eine Reihe von Knoten in eine Cron-Task geladen wird, die Taxonomie-Termreferenzen leeren und einige Änderungen anwenden:

/**
 * Implements hook_cron().
 */
function MYMODULE_cron() {
  $query = new EntityFieldQuery();
  $query
    ->entityCondition('entity_type', 'node')
    ->entityCondition('bundle', 'property')
    ->propertyOrderBy('changed', 'DESC')
    ->addTag('type_is_null')
    ->range(0,50); // Maximum of 50.
  $result = $query->execute();

  if (!empty($result['node'])) {
    $nids = array_keys($result['node']);
    $nodes = node_load_multiple($nids);

    foreach ($nodes as $node) {
      // do_some_stuff($node);
    }
  }
}

/**
 * Implements hook_query_TAG_alter()
 */
function MYMODULE_query_type_is_null_alter(QueryAlterableInterface $query) {
  $query->leftJoin('field_data_field_foo', 'f', 'node.nid = f.entity_id AND f.entity_type = :entity_type');
  $query->isNull('f.field_foo_tid'); // Check name by SQL: DESC field_data_field_foo

  $query->leftJoin('field_data_field_bar', 'b', 'node.nid = b.entity_id AND b.entity_type = :entity_type');
  $query->isNull('b.field_bar_tid'); // Check name by SQL: DESC field_data_field_bar
}
Kenorb
quelle
3

Sie müssen Null in Anführungszeichen setzen.

->fieldCondition('field_name', 'value', 'NULL', '!=');
Sharique
quelle
2

Bitte korrigieren Sie mich, falls ich falsch liege. Es scheint, dass es einfach sein muss

$query->fieldCondition('field_name');

um alle Knoten mit einem leeren field_nameFeld auszuschließen o_O

In Drupal getestet version >= 7.43.

leymannx
quelle
Das funktioniert tatsächlich. Die positiveren Antworten waren für mich fehlerhaft (es konnte kein Fehler angezeigt werden, aber es wurde alles kaputt gemacht).
Joren