Drupal 8:基于Search API索引的视图分组过滤器实现问询
在Drupal 8/9中使用Search API实现分组过滤器(AND/OR条件)
我完全理解你的困扰——Drupal 8/9的Search API文档在复杂过滤器分组这块确实不够清晰,不过其实它的核心逻辑和Drupal 7是一脉相承的,只是有些细节需要适配新的架构。下面我就给你详细讲讲如何实现带AND/OR条件的分组过滤器,包括视图查询alter和自定义查询两种场景:
一、在视图查询Alter中实现分组过滤器
和Drupal 7类似,我们依然使用hook_search_api_views_query_alter钩子,只是视图对象类型变为ViewExecutable,但SearchApiViewsQuery的核心方法基本保留。
基础示例:独立AND/OR分组
/** * Implements hook_search_api_views_query_alter(). */ function mymodule_search_api_views_query_alter(ViewExecutable &$view, SearchApiViewsQuery &$query) { // 仅针对目标视图和显示执行逻辑 if ($view->id() !== 'my_custom_view' || $view->current_display !== 'page_1') { return; } // 1. 创建AND分组过滤器:同时满足多个条件 $and_filter = $query->createFilter('AND'); $and_filter->condition('field_content_type', 'article'); // 内容类型为文章 $and_filter->condition('field_published_date', strtotime('-30 days'), '>'); // 30天内发布 // 将AND过滤器加入主查询(默认与已有条件为AND关系) $query->filter($and_filter); // 2. 创建OR分组过滤器:满足任一条件即可 $or_filter = $query->createFilter('OR'); $or_filter->condition('field_featured', TRUE); // 推荐内容 $or_filter->condition('field_popularity', 100, '>='); // 热度≥100 // 将OR过滤器加入主查询,指定与已有条件为OR关系 $query->filter($or_filter, 'OR'); }
进阶示例:嵌套分组((A AND B) OR (C AND D))
如果需要更复杂的逻辑组合,可以嵌套过滤器:
/** * Implements hook_search_api_views_query_alter(). */ function mymodule_search_api_views_query_alter(ViewExecutable &$view, SearchApiViewsQuery &$query) { if ($view->id() !== 'my_complex_view') { return; } // 外层OR过滤器:两个AND组满足其一即可 $outer_or = $query->createFilter('OR'); // 内层AND组1:(内容类型=文章 AND 状态=已发布) $inner_and1 = $query->createFilter('AND'); $inner_and1->condition('field_content_type', 'article'); $inner_and1->condition('field_status', 'published'); // 内层AND组2:(内容类型=页面 AND 推荐=是) $inner_and2 = $query->createFilter('AND'); $inner_and2->condition('field_content_type', 'page'); $inner_and2->condition('field_featured', TRUE); // 将两个内层AND组加入外层OR组 $outer_or->filter($inner_and1); $outer_or->filter($inner_and2); // 将嵌套过滤器加入主查询 $query->filter($outer_or); }
二、自定义代码中直接创建Search API查询
如果不是通过视图,而是自定义代码查询Search API索引,用法也类似:
// 加载目标索引 $index = \Drupal\search_api\Entity\Index::load('my_content_index'); // 创建查询对象 $query = $index->query(); // 创建OR分组过滤器 $or_filter = $query->createFilter('OR'); $or_filter->condition('field_tags', 'tech'); $or_filter->condition('field_category', 'tutorial'); // 将过滤器加入查询 $query->filter($or_filter); // 执行查询并获取结果 $results = $query->execute();
关键要点说明
createFilter($conjunction):参数$conjunction为'AND'或'OR',定义当前过滤器组内条件的组合逻辑condition($field, $value, $operator = '='):支持多种操作符(>、<、IN、NOT IN等),注意字段名是Search API索引中配置的机器名(而非实体字段原名)filter($filter, $conjunction = 'AND'):将子过滤器添加到父过滤器/主查询时,第二个参数定义该子过滤器与已有条件的组合关系
内容的提问来源于stack exchange,提问作者Olli Bolli
相关产品推荐
相关产品推荐

