Excluindo campos vazios (nulos) ao usar a condição de consulta EntityFieldQuery


31

É possível selecionar todas as entidades cujo campo xyz está vazio?

Eu tentei algo assim:

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

No entanto, isso não parece funcionar.

Alguma ideia?

Respostas:


19

Se você olhar na página de documentação do fieldCondition , verá o seguinte aviso:

Observe que entidades com valores de campos vazios serão excluídas dos resultados EntityFieldQuery ao usar esse método.

A verificação da existência ou não de um campo foi adicionada ao entityFieldQuery no Drupal 8, mas infelizmente não será suportada para o Drupal 7 .

Existem vários métodos para conseguir isso:

  1. Usando uma tag e hook_query_TAG_alter, conforme mencionado por @Clive, consulte o comentário 4 sobre a questão do Drupal para obter um exemplo;
  2. Primeiro, consulte todas as entradas que não sejam NULL, depois todas as entradas, exceto as anteriores, conforme descrito na resposta de @ seddonym e no comentário 5 sobre o problema do Drupal ;
  3. Você pode escrever sua 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();

15

Você pode usar != NULL, mas não pode usar = NULLpor algum motivo.

Esta é a minha solução alternativa.

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

10

De acordo com a documentação, você pode usar null e isnull; apenas tem uma maneira específica de escrevê-lo.

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

9

A resposta curta é que diretamente, não, você não pode (consulte EntityFieldQuery não suporta isNull ou isNotNull ). Se bem me lembro, esse é um efeito colateral do fato de que EntityFieldQueryusa apenas INNER JOINs para juntar tabelas.

Existe uma solução alternativa, porém, que envolve o uso hook_query_TAG_alter()e a adição de uma tag à sua EntityFieldQuery, há um exemplo no último comentário na página que eu vinculei acima.


5

No Drupal 7, verifique a seguinte solução proposta aqui :

Registre a tag para alterar a instância da 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 .: Essa alteração da tag de consulta funciona apenas para o tipo de entidade "nó". Não confunda "tags de campo" relacionadas ao vocabulário "Tags", pois pode haver outras como "Categorias".

Obtenha todos os nós que ainda não foram marcados usando EntityFieldQuery, veja o 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();
?>

Outro exemplo:

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

Então eu implementei, hook_query_TAG_alteraproveitando o fato que my_custom_tagé definido apenas por mim:

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

Outro exemplo:

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

Exemplo mais completo abaixo, que carrega vários nós na tarefa cron, que esvazia referências de termos de taxonomia e aplica algumas mudanças:

/**
 * 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
}

3

Você precisa agrupar Nulo entre aspas.

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

2

Por favor me corrija se eu estiver errado. Parece que ele simplesmente precisa ser

$query->fieldCondition('field_name');

excluir todos os nós com um field_namecampo vazio o_O

Testado em Drupal version >= 7.43.


Isso realmente funciona. As respostas mais votadas foram erradas para mim (não conseguiram exibir um erro, mas estavam quebrando tudo).
Joren 25/01
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.