Excluir campos vacíos (nulos) cuando se usa la condición de consulta EntityFieldQuery

31

¿Es posible seleccionar todas las entidades cuyo campo xyz está vacío?

Intenté algo así:

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

Sin embargo, esto no parece funcionar.

¿Algunas ideas?

David Barratt
fuente

Respuestas:

19

Si mira en la página de documentación de FieldCondition , verá la siguiente advertencia:

Tenga en cuenta que las entidades con valores de campo vacíos se excluirán de los resultados de EntityFieldQuery al usar este método.

Comprobando si un campo existe o no se ha agregado a entityFieldQuery en Drupal 8, pero desafortunadamente no se transferirá a Drupal 7 .

Hay varios métodos para lograr esto:

  1. Usando una etiqueta y hook_query_TAG_alter como lo menciona @Clive, vea el comentario 4 sobre el problema de Drupal como ejemplo;
  2. Primero consulte todas las entradas que no sean NULL, luego consulte todas las entradas, excepto las anteriores, como se describe en la respuesta de @ seddonym y en el comentario 5 sobre el problema de Drupal ;
  3. Puede escribir su consulta usando SelectQuery rathen que EntityfieldQuery como tal:

_ _

$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
fuente
15

Puede usar != NULL, pero no puede usar = NULLpor alguna razón.

Esta es mi solución.

  //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
fuente
10

De acuerdo con la documentación , puede usar null e isnull; solo tiene una forma específica de escribirlo.

$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
fuente
9

La respuesta corta es que directamente, no, no puedes (ver EntityFieldQuery no es compatible con isNull o isNotNull ). Si recuerdo bien, este es un efecto secundario del hecho de que EntityFieldQuerysolo usa INNER JOINs para unir tablas.

Sin embargo, existe una solución alternativa, que implica el uso hook_query_TAG_alter()y la adición de una etiqueta a su nombre EntityFieldQuery, hay un ejemplo en el último comentario en la página a la que hice el enlace anterior.

Clive
fuente
5

En Drupal 7, compruebe la siguiente solución propuesta aquí :

Registre la etiqueta para modificar la instancia de consulta:

<?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 .: Esta alteración de etiqueta de consulta solo funciona para el tipo de entidad "nodo". No confunda "field_tags" relacionado con el vocabulario "Etiquetas", puede ser cualquier otro como "Categorías".

Obtenga todos los nodos que aún no se han etiquetado con EntityFieldQuery, mire el método addTag ():

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

Otro ejemplo:

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

Luego implementé hook_query_TAG_alteraprovechando el hecho de que my_custom_tagsolo lo establezco yo:

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

Otro ejemplo:

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

Un ejemplo más completo a continuación que carga un montón de nodos en la tarea cron que vacía referencias de términos de taxonomía y aplica algunos cambios:

/**
 * 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
fuente
3

Necesita envolver Null entre comillas.

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

Por favor corrígeme si estoy equivocado. Parece que simplemente necesita ser

$query->fieldCondition('field_name');

para excluir todos los nodos con un field_namecampo vacío o_O

Probado en Drupal version >= 7.43.

leymannx
fuente
Eso realmente funciona. Las respuestas más votadas me estaban dando errores (no podía hacer que mostrara un error, pero estaba rompiendo todo).
Joren