Z wyłączeniem pustych pól (Null) podczas korzystania z warunku zapytania EntityFieldQuery

31

Czy można zaznaczyć wszystkie podmioty, których pole xyz jest puste?

Próbowałem czegoś takiego:

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

To jednak nie działa.

Jakieś pomysły?

David Barratt
źródło

Odpowiedzi:

19

Jeśli spojrzysz na stronę dokumentacji pola Warunek , zobaczysz następujące ostrzeżenie:

Należy zauważyć, że encje z pustymi wartościami pól zostaną wykluczone z wyników EntityFieldQuery podczas korzystania z tej metody.

Sprawdzanie, czy pole istnieje, czy nie zostało dodane do encjiFieldQuery w Drupal 8, ale niestety nie zostanie przeniesione do Drupal 7 .

Istnieją różne metody osiągnięcia tego celu:

  1. Używając tagu i hook_query_TAG_alter, jak wspomniano w @Clive, zobacz na przykład komentarz 4 na temat Drupala ;
  2. Najpierw przeszukaj wszystkie wpisy inne niż NULL, a następnie przeszukaj wszystkie wpisy oprócz poprzednich, jak opisano w odpowiedzi @ seddonym i w komentarzu 5 na temat Drupala ;
  3. Możesz napisać zapytanie, używając SelectQuery rathen niż EntityfieldQuery jako takie:

_

$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
źródło
15

Możesz użyć != NULL, ale = NULLz jakiegoś powodu nie możesz .

To jest moje obejście.

  //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
źródło
10

Zgodnie z dokumentacją można użyć wartości null i isnull; po prostu ma określony sposób na napisanie tego.

$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
źródło
9

Krótka odpowiedź brzmi: nie, nie możesz (patrz EntityFieldQuery nie obsługuje isNull lub isNotNull ). Jeśli dobrze pamiętam, jest to efekt uboczny tego, że do łączenia tabel EntityFieldQueryużywa tylko INNER JOINs.

Istnieje jednak obejście, które polega na używaniu hook_query_TAG_alter()i dodawaniu tagu do twojego EntityFieldQuery, w ostatnim komentarzu na stronie , do której odsyłam , znajduje się przykład.

Clive
źródło
5

W Drupal 7 sprawdź następujące obejście proponowane tutaj :

Zarejestruj znacznik, aby zmienić instancję zapytania:

<?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');
}
?>

Obs .: Ta zmiana tagu zapytania działa tylko dla typu encji „węzeł”. Nie myl „tagów_pola” związanych ze słownictwem „tagów”, mogą być dowolne inne jak „kategorie”.

Pobierz wszystkie węzły, które nie zostały jeszcze otagowane przy użyciu EntityFieldQuery, spójrz na metodę addTag ():

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

Inny przykład:

  $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();

Następnie hook_query_TAG_alterwdrożyłem wykorzystanie faktu, który my_custom_tagsam ustaliłem:

/**
 * 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');
}

Inny przykład:

<?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();  
  }
?>

Bardziej kompletny przykład poniżej, który ładuje wiązkę węzłów do zadania cron, które opróżniają odwołania do terminologii taksonomii i wprowadzają pewne zmiany:

/**
 * 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
źródło
3

Musisz wpisać Null w cudzysłów.

->fieldCondition('field_name', 'value', 'NULL', '!=');
Sharique
źródło
2

Proszę popraw mnie jeżeli się mylę. Wydaje się, że tak po prostu musi być

$query->fieldCondition('field_name');

aby wykluczyć wszystkie węzły z pustym field_namepolem o_O

Testowane w Drupal version >= 7.43.

leymannx
źródło
To faktycznie działa. Więcej pozytywnych odpowiedzi było dla mnie błędem (nie mogłem wyświetlić błędu, ale wszystko zepsuło).
Joren