使用EntityFieldQuery查询条件时排除空(Null)字段


31

是否可以选择所有xyz字段为空的实体?

我试过这样的东西:

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

但是,这似乎不起作用。

有任何想法吗?

Answers:


19

如果您查看fieldCondition文档页面,则会看到以下警告:

请注意,使用此方法时,具有空字段值的实体将从EntityFieldQuery结果中排除。

检查字段是否存在已被添加到Drupal 8的entityFieldQuery中,但是不幸的是不会被反向移植到Drupal 7中

有多种方法可以实现此目的:

  1. 使用@Clive提到的tag和hook_query_TAG_alter,有关示例,请参阅有关Drupal问题的评论4
  2. 首先查询所有非NULL条目,然后查询除先前条目以外的所有条目,如@seddonym的答案和有关Drupal问题的注释5中所述
  3. 您可以使用SelectQuery而不是EntityfieldQuery 编写查询,如下所示:

_

$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

您可以使用!= NULL,但= NULL由于某种原因不能使用。

这是我的解决方法。

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

根据文档,您可以使用null和isull。它只有一种特定的编写方式。

$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

简短的答案是,直接,不,您不能(请参阅EntityFieldQuery不支持isNull或isNotNull)。如果我没记错的话,这是EntityFieldQuery仅使用INNER JOINs联接表的事实的副作用。

不过,有一种解决方法,涉及使用hook_query_TAG_alter()标记并将标记添加到中EntityFieldQuery,我上面链接到的页面的最后一个注释中有一个示例。


5

在Drupal 7请提出以下解决方法在这里

注册标签以更改查询实例:

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

观察:此查询标记alter仅适用于“节点”实体类型。不要混淆与“标签”词汇相关的“ field_tags”,可以是“类别”之类的任何其他词。

使用EntityFieldQuery获取尚未标记的所有节点,请查看addTag()方法:

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

其他例子:

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

然后,我hook_query_TAG_alter利用了我自己my_custom_tag设定的事实来 实施:

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

另一个例子:

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

下面是一个更完整的示例,该示例在cron任务上加载了一堆节点,这些节点上的空分类术语引用并应用了一些更改:

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

您需要将Null括在引号中。

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

2

如果我错了,请纠正我。似乎只需要

$query->fieldCondition('field_name');

排除所有具有空field_name字段o_O的节点

在Drupal中测试过version >= 7.43


确实有效。他们对问题的更高评价对我来说是错误的(无法显示错误,但是破坏了一切)。
Joren
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.