关于 drupal-search-api
面向 Drupal Search API 网站开发者,整理索引字段、搜索提升处理器和配置管理的实践模式。涵盖布尔字段与数值字段提升、重建索引及结果验证。
主要功能
- 01配置布尔字段与数值字段
- 02创建自定义提升处理器
- 03组合内容与互动指标提升
- 04管理并核验 Search API 配置
- 05清理并重建搜索索引
- 06测试搜索结果与排序
适用场景
- 01提高精选内容在搜索中的排名
- 02按收藏或浏览量调整结果排序
- 03排查处理器冲突或提升未生效
- 04配置变更后重建并验证索引
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ grasmash/ drupal-claude-skills --skill drupal-search-api安装后在 Claude Code 中输入/drupal-search-api确认已加载。
详细介绍
Drupal Search API 模式
本技能介绍 Drupal 网站的 Search API 配置模式、加权策略和自定义处理器开发。
索引配置
字段类型要求
用于加权的布尔字段
- 布尔字段最适合搭配自定义加权处理器使用
- 整数字段可能会导致基于布尔值的加权逻辑出现问题
- 始终在索引设置中将布尔字段配置为
type: boolean
field_settings:
field_featured:
label: Featured
datasource_id: 'entity:node'
property_path: field_featured
type: boolean # NOT integer
boost: 8.0
配置命令
ddev drush config:set search_api.index.{index_name} \
field_settings.field_featured.type boolean
用于互动度加权的数值字段
标记计数字段
- 计数字段使用
type: integer - 由
flag_search_api模块管理 - 自动编入索引并更新
field_settings:
flag_bookmark_count:
label: 'Bookmark count'
property_path: flag_bookmark_count
type: integer
flag_favorite_count:
label: 'Favorite count'
property_path: flag_favorite_count
type: integer
加权处理器
自定义布尔加权处理器
适用场景
- 布尔字段加权(精选标记、推广内容)
- 需要完全控制加权逻辑
- 复杂的条件加权
模式:FeaturedContentBoost.php
<?php
namespace Drupal\custom_search\Plugin\search_api\processor;
use Drupal\search_api\Item\ItemInterface;
use Drupal\search_api\Processor\ProcessorPluginBase;
/**
* @SearchApiProcessor(
* id = "featured_content_boost",
* label = @Translation("Featured content boost"),
* description = @Translation("Adds a boost to indexed items marked as featured."),
* stages = {
* "preprocess_index" = 0,
* },
* locked = false,
* hidden = false,
* )
*/
class FeaturedContentBoost extends ProcessorPluginBase {
/**
* {@inheritdoc}
*/
public function preprocessIndexItems(array $items) {
/** @var \Drupal\search_api\Item\ItemInterface $item */
foreach ($items as $item) {
try {
$entity = $item->getOriginalObject()->getValue();
// Check if entity has featured field and it's set to TRUE.
if ($entity->hasField('field_featured') &&
!$entity->get('field_featured')->isEmpty() &&
$entity->get('field_featured')->value == 1) {
$old_boost = $item->getBoost();
// Apply 2x boost to featured content.
$item->setBoost($old_boost * 2.0);
}
}
catch (\Exception $e) {
// Skip items that can't be loaded.
continue;
}
}
}
}
要点
- 使用乘法加权:
$item->setBoost($old_boost * boost_factor) - 模式参考
search_api_boolean_field_boost模块 - 在索引时通过
preprocess_index阶段加权 - 始终先获取旧的加权值,以保留其他加权
建议的加权系数
- 精选内容:
2.0x(适度但有效) - 精选内容:
1.5x - 3.0x - 高级内容:
1.5x - 2.0x
数值字段加权处理器
适用场景
- 互动度指标(点赞、书签、浏览量)
- 数值质量评分
- 基于时间的衰减系数
配置模式
processor_settings:
number_field_boost:
weights:
preprocess_index: 0
boosts:
flag_bookmark_count:
boost_factor: 0.01
aggregation: max
flag_favorite_count:
boost_factor: 0.1
aggregation: max
工作原理
- 根据字段值增加加权值
- 公式:
boost += (field_value * boost_factor) - 示例:138 个书签 x 0.01 = 加权值增加 1.38
配置命令
# Set bookmark count boost (0.01 per bookmark)
ddev drush config:set search_api.index.{index_name} \
processor_settings.number_field_boost.boosts.flag_bookmark_count.boost_factor 0.01
# Set favorite count boost (0.1 per favorite)
ddev drush config:set search_api.index.{index_name} \
processor_settings.number_field_boost.boosts.flag_favorite_count.boost_factor 0.1
建议的加权系数
- 书签数:
0.01 - 0.05(计数范围为 10-1000) - 收藏数:
0.1 - 0.5(计数范围为 1-50) - 浏览量:
0.001 - 0.01(计数范围为 100-10000)
处理器冲突
问题:多个处理器作用于同一字段
如果多个处理器针对同一字段,它们可能会发生冲突:
- 一个处理器覆盖另一个
- 加权值无法按预期叠加
- 结果不可预测
解决方案:移除冲突配置
# Remove field from number_field_boost if using custom processor
ddev drush config:set search_api.index.{index_name} \
processor_settings.number_field_boost.boosts.field_featured null
最佳实践
- 对布尔值或复杂逻辑使用自定义处理器
- 对简单的数值加权使用 number_field_boost
- 不要在多个处理器中配置同一字段
配置管理
使用 PHP 直接更新配置
如果 drush config:set 失败或产生意外结果(例如对无关配置产生副作用),请使用 PHP 直接更新活动配置:
ddev drush php:eval "
\$config = \Drupal::configFactory()->getEditable('search_api.index.{index_name}');
// Set field type
\$config->set('field_settings.field_featured.type', 'boolean');
// Remove from number_field_boost
\$boosts = \$config->get('processor_settings.number_field_boost.boosts');
unset(\$boosts['field_featured']);
\$config->set('processor_settings.number_field_boost.boosts', \$boosts);
// Set boost factors
\$config->set('processor_settings.number_field_boost.boosts.flag_bookmark_count.boost_factor', 0.01);
\$config->set('processor_settings.number_field_boost.boosts.flag_favorite_count.boost_factor', 0.1);
\$config->save();
echo \"Configuration updated\n\";
"
使用 PHP 而非 drush config:set 的场景:
- config:set 产生不必要的副作用时(例如将
server: {server_name}改为server: null) - 移除数组键时(使用 unset 模式比设为
null更合适) - 需要以原子方式进行多项相关更改时
- 字段类型更改导致 Drupal 回退到通用类型时
使用 PHP 更新配置后:
- 验证更改:
ddev drush config:get search_api.index.{index_name} field_settings.field_featured - 导出该对象:
ddev drush config:get search_api.index.{index_name} --format=yaml > config/default/search_api.index.{index_name}.yml(直接执行config:export也会导出无关的配置漂移;请参阅drupal-config-mgmt技能) - 检查导出的更改:
git diff config/default/ - 还原任何非预期的更改(例如,将 ngram 字段改为纯文本)
字段类型保留
问题: 修改 Solr 服务配置(例如,指向不同的后端)时,导出配置可能会将自定义字段类型降级为通用类型:
# BEFORE (correct)
field_display_name:
type: 'solr_text_custom:ngramstring'
# AFTER export (incorrect)
field_display_name:
type: text
解决方案: 导出后,通过 PHP 恢复自定义字段类型:
ddev drush php:eval "
\$config = \Drupal::configFactory()->getEditable('search_api.index.{index_name}');
\$config->set('field_settings.field_display_name.type', 'solr_text_custom:ngramstring');
\$config->set('field_settings.label.type', 'solr_text_custom:ngramstring');
\$config->set('field_settings.name.type', 'solr_text_custom:ngramstring');
\$config->set('field_settings.title.type', 'solr_text_custom:ngramstring');
\$config->save();
"
ddev drush config:get search_api.index.{index_name} --format=yaml > config/default/search_api.index.{index_name}.yml
使用 ngram 分词的字段:
field_display_name- 显示名称(用于自动完成的部分匹配)label- 实体标签/标题name- 用户账户名称title- 节点标题
绝不要将这些字段改为 type: text——这会导致部分名称匹配失效(例如,搜索“mich”将无法找到“Michael”)。
配置导出的副作用
修改 Search API 服务配置(例如用于本地开发)时,Drupal 可能会更新索引配置,以移除对服务的依赖:
# Unintended change in search_api.index.{index_name}.yml
dependencies:
config:
- - search_api.server.{server_name} # Removed
server: null # Changed from {server_name}
预防措施:
- 本地开发时不要修改
search_api.server.{server_name}.yml - 使用 DDEV 内置的 Solr 服务,不要更改服务配置
- 如果需要更改服务配置,请使用配置拆分处理特定环境的设置
- 提交前务必检查
git diff config/default/
恢复:
# Revert index files if server was set to null
git checkout HEAD -- config/default/search_api.index.*.yml
更改后重新索引
需要重新索引的情况
以下情况务必重新索引:
- 更改字段类型(integer -> boolean)
- 更改 boost 因子
- 添加/移除处理器
- 修改处理器配置
重新索引命令
# Full reindex workflow
ddev drush cr
ddev drush search-api:clear {index_name}
ddev drush search-api:index {index_name}
# Check index status
ddev drush search-api:status {index_name}
部分重新索引
# Index only remaining items (incremental)
ddev drush search-api:index {index_name}
# Clear and reindex specific items (not available in core)
# Use full reindex instead
测试 Boost
Search API Drush 命令
# Test search via drush
ddev drush search-api:search {index_name} "search query"
# Check indexed values
ddev drush search-api:status {index_name}
Web 端点测试
# Test via web search endpoint
curl -H "Accept: application/vnd.api+json" \
"https://example.com/search-api/web-search?query=test"
# Parse results with Python
curl -s "https://example.com/search-api/web-search?query=test" | \
python3 -c "import sys, json; data = json.load(sys.stdin); \
[print(f'{i+1}. {item[\"attributes\"][\"title\"]}') \
for i, item in enumerate(data['data'][:10])]"
验证查询
检查书签数量
SELECT u.uid, u.name, fcf.count AS bookmark_count
FROM users_field_data u
LEFT JOIN flag_counts fcf ON fcf.entity_type = 'user'
AND fcf.entity_id = u.uid
AND fcf.flag_id = 'bookmark'
ORDER BY fcf.count DESC
LIMIT 10;
检查收藏数量
SELECT n.nid, n.title, fcl.count AS favorite_count
FROM node_field_data n
INNER JOIN flag_counts fcl ON fcl.entity_type = 'node'
AND fcl.entity_id = n.nid
AND fcl.flag_id = 'favorite'
WHERE n.type = 'article'
ORDER BY fcl.count DESC
LIMIT 10;
性能注意事项
索引时 Boost 与查询时 Boost
索引时 Boost(推荐)
- 性能更好(在索引期间计算一次)
- 可应对高查询量
- Boost 逻辑更改后需要重新索引
- Boost 是静态的(无法按查询调整)
查询时 Boost
- 动态(可按查询调整)
- 更改后无需重新索引
- 每次查询都会受到性能影响
- 使用 Search API 实现起来较复杂
推荐模式:索引时 Boost
- 所有 Boost 均在
preprocess_index阶段应用 - 更适合高流量搜索
- 重新索引的要求可以接受
Boost 叠加
Boost 的组合方式
- 基础相关性得分(来自 Solr)
- 特色内容 Boost:
score x 2.0 - 书签数量 Boost:
score + (bookmarks x 0.01) - 收藏数量 Boost:
score + (favorites x 0.1)
计算示例
Node: "Getting Started with Drupal" (featured, 138 bookmarks)
- Base score: 1.0
- Featured: 1.0 x 2.0 = 2.0
- 138 bookmarks: 2.0 + (138 x 0.01) = 3.38
- Final boost: 3.38
Node: "Advanced Drupal Techniques"
- Base score: 1.0
- 12 favorites: 1.0 + (12 x 0.1) = 2.2
- Final boost: 2.2
常见问题
问题:未应用 Boost
症状
- 结果排名不符合预期
- 重新索引后没有变化
检查清单
- 已在索引配置中启用处理器
- 字段类型正确(boolean/integer)
- 已完成完整重新索引
- 没有冲突的处理器
- 配置更改后已清除缓存
调试命令
# Check processor configuration
ddev drush config:get search_api.index.{index_name} processor_settings
# Check field configuration
ddev drush config:get search_api.index.{index_name} field_settings
# Verify index status
ddev drush search-api:status {index_name}
问题:Boost 过强/过弱
症状
- 不相关的结果排名过高
- 重要结果排名不够高
解决方案:调整 Boost 因子
过强(主导相关性):
- 降低乘法 Boost(2.0 -> 1.5)
- 降低加法 Boost 因子(0.1 -> 0.05)
过弱(效果不明显):
- 逐步提高 Boost 因子
- 使用极端值测试以确认功能正常,然后逐步调低
测试模式
- 从保守的 Boost 值(1.5x 或 0.01)开始
- 使用已知查询进行测试
- 逐步提高,直到效果明显
- 调低至最佳水平
模块依赖项
必需模块
search_api- Search API 核心模块search_api_solr- Solr 后端(如果使用 Solr)
可选模块
flag_search_api- 对标记计数(书签、收藏)建立索引search_api_boolean_field_boost- Boost 模式参考
参考资料
搜索 API 处理器开发
提升策略
Flag Search API
- Flag Search API 模块
- 提供用于互动度指标的标记计数索引