Использование OR с EntityFieldQuery

У меня никогда не было необходимости делать это до сегодняшнего дня, но похоже, что вы не можете делать OR-запросы с помощью EntityFieldQuery, так как

Пример будет получен для всех объектов, у которых есть поле даты, где значение равно null или после сегодняшнего дня.

Я пропустил что-то или какой-то трюк или это просто не поддерживается?

24 голоса | спросил googletorp 1 22011vEurope/Moscow11bEurope/MoscowTue, 01 Nov 2011 13:55:38 +0400 2011, 13:55:38

5 ответов


22

Я видел решение этой проблемы . Идея состоит в том, чтобы использовать addTag() в запросе и реализовать hook_query_TAG_alter(), где у вас есть старый добрый SelectQuery.

ответил Michael 18 MarpmSun, 18 Mar 2012 19:21:03 +04002012-03-18T19:21:03+04:0007 2012, 19:21:03
12

Вы можете подстроить EntityFieldQuery и переопределить некоторые методы.

В массив добавляются условия, добавляемые к объекту класса EntityFieldQuery (например, условие свойства).

  public function propertyCondition($column, $value, $operator = NULL) {
    // The '!=' operator is deprecated in favour of the '<>' operator since the
    // latter is ANSI SQL compatible.
    if ($operator == '!=') {
      $operator = '<>';
    }
    $this->propertyConditions[] = array(
      'column' => $column, 
      'value' => $value, 
      'operator' => $operator,
    );
    return $this;
  }

Когда запрос строится, этот массив затем используется в цикле, подобном следующему (код присутствует в

foreach ($this->propertyConditions as $property_condition) { $this->addCondition($select_query, "$base_table." . $property_condition['column'], $property_condition); } содержит значение, возвращаемое при вызове $select_query.

ответил kiamlaluno 1 22011vEurope/Moscow11bEurope/MoscowTue, 01 Nov 2011 14:30:57 +0400 2011, 14:30:57
6

Не нужно разделить запросы на 2 и слить или что-нибудь в этом роде. Просто нужно изменить запрос

Рассмотрим сценарий: У меня было 2 типа сущностей с именами машин: заявления tincan и tincan_agents

5 полей ссылки объекта на сущности

4 из них являются регулярными ссылочными полями сущности, а пятый (tincan_object) является ссылочным полем с несколькими сущностями, каждое ссылочное поле ссылается на объекты типа «Агент».

Поле ссылки tincan_object может ссылаться на агенты и действия (третий тип сущности). Агент имеет свойство object_type, которое может быть либо агентом, либо группой.

Я хочу найти любое заявление, которое ссылается на один из нескольких возможных агентов, в любом из полей ссылки. Нам нужен оператор OR между полямиConditions, но нам также нужно проверить object_type ссылочного поля типа множественной сущности и убедиться, что это одна из двух возможностей.

Нижеприведенный ниже код является самым простым, в нашем решении в запросе было много других условий, полей и т. д., поэтому код должен был не учитывать порядок условий или даже если все эти поля были запрошены .

    $query = new EntityFieldQuery();
    $query->entityCondition('entity_type', 'tincan_statement');

    $all_agents = array(4,10); //entity_ids to search for
    $query->addTag('tincan_statement_get_agents');
    $query->fieldCondition('tincan_actor', 'target_id', $all_agents, 'IN'); 
    //need OR between fields conditions
    $query->fieldCondition('tincan_authority', 'target_id', $all_agents, 'IN');
//need OR between fields conditions
    $query->fieldCondition('tincan_instructor', 'target_id', $all_agents, 'IN');
//need OR between fields conditions
    $query->fieldCondition('tincan_team', 'target_id', $all_agents, 'IN');
//need OR between fields conditions
//but then nested in the OR structure we need an AND for two columns of the multientity type reference field tincan_object
    $query->fieldCondition('tincan_object', 'target_id', $all_agents, 'IN');
    $query->fieldCondition('tincan_object', 'object_type', array('Agent', 'Group'), 'IN');
    $results = $query->$execute();

Решение: Обратите внимание на приведенный выше EntityFieldQuery

 $query->addTag('tincan_statement_get_agents');

Это теги запроса, позволяющие реализовать hook_query_TAG_alter ()

/**
 * Implements hook_query_TAG_alter()
 * alters the query for finding agents with or without the related_agents flag
 * used for Statement API Get processor EntityFieldQuery
 */
function tincan_lrs_query_tincan_statement_get_agents_alter(QueryAlterableInterface $query) {
  //need to or the search for all the fields (actor, object, authority, instructor, team)
  // the object_type of the object field needs to be Agent OR Group

  $conditions =& $query->conditions();
  // dsm($conditions);  //dsm() is your friend! comes with devel module
  $agent_grouping_condition = db_or(); 
  $object_parameters = array();
  $x = 0;
  foreach ($conditions as $key => $condition) {
    if (is_numeric($key) && isset($condition['field']) && is_scalar($condition['field'])) {
      if ( (strpos($condition['field'], 'tincan_object_object_type') !== FALSE  ||
          strpos($condition['field'], 'tincan_object_target_id') !== FALSE ) && $condition['operator'] == 'IN') {
  //u
            unset($conditions[$key]);
            $object_parameters[$x]['field'] = $condition['field'];
            $object_parameters[$x]['value'] = $condition['value'];
            $object_parameters[$x]['operator'] = $condition['operator'];
            $x += 1;
          }

       if(strpos($condition['field'], 'tincan_actor_target_id') !== FALSE ||
          strpos($condition['field'], 'tincan_instructor_target_id') !== FALSE ||
          strpos($condition['field'], 'tincan_team_target_id') !== FALSE ||
          strpos($condition['field'], 'tincan_authority_target_id') !== FALSE ) {
            unset($conditions[$key]);
            $agent_grouping_condition->condition($condition['field'], $condition['value'], $condition['operator']);

      } 
    }
  }

  // create new AND condition to nest in our OR condition set for the object parameters
  $object_condition = db_and();
  foreach($object_parameters as $key => $param) {
    $object_condition->condition($param['field'], $param['value'], $param['operator']);
  }

  $agent_grouping_condition->condition($object_condition);

  $query->condition($agent_grouping_condition);

  //By default EntityFieldQuery uses inner joins, change to left
  $tables =& $query->getTables();

  foreach($tables as $key => $table) {
    if (strpos($key, 'field_data_tincan_object') !== FALSE ||
        strpos($key, 'field_data_tincan_actor') !== FALSE ||
        strpos($key, 'field_data_tincan_authority') !== FALSE ||
        strpos($key, 'field_data_tincan_instructor') !== FALSE ||
        strpos($key, 'field_data_tincan_team') !== FALSE ) {
          if(!is_null($table['join type'])) {
            $tables[$key]['join type'] = 'LEFT';
          }
    }
  }

}
ответил jackrabbithanna 24 J000000Friday15 2015, 22:43:06
5

Вы не можете бояться, ORs не поддерживается на основе класса EntityFieldQuery.

В один конец можно добавить тег к запросу с помощью ->addTag(), а затем реализовать hook_query_TAG_alter() , чтобы вручную изменить внутреннюю структуру запроса для запросов, содержащих этот тег.

Выполняя это, вы сможете прокрутить существующие условия и внести необходимые изменения, чтобы добавить логику OR. Однако это не очень хороший способ сделать это; вы можете найти пример здесь .

ответил Clive 3 PMpTue, 03 Apr 2012 14:13:32 +040013Tuesday 2012, 14:13:32
2

OP хочет запросить сущности с датой null или больше, чем x, я хотел запросить узлы, не имеющие языка, или язык пользователя. addTag() - лучшее решение для добавления фактического оператора OR, но в моем случае оно будет излишним. Мое очень простое ИЛИ может быть выполнено путем поиска свойства языка в массиве с помощью:

$query->propertyCondition('language', array($GLOBALS['language']->language, LANGUAGE_NONE), 'IN');
ответил lmeurs 3 J000000Wednesday13 2013, 11:37:58

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132