clarkwinkelmann / flarum-ext-scout
为 Flarum 提供的 Algolia 和 Meilisearch 搜索
Requires
Requires (Dev)
README
集成 Laravel Scout 与 Flarum 讨论和用户搜索。
与 Laravel 类似,每次在 Flarum 中更新模型时,数据都会自动与搜索索引同步。您只需要在启用扩展时手动导入数据(请参阅下面的命令)。
外部搜索驱动程序在服务器端用于过滤 MySQL 结果,因此它应该仍然与其他扩展和搜索策略兼容。
扩展中包含 Algolia 和 Meilisearch 驱动程序。支持 TNTSearch,但需要手动安装额外的包。Scout 数据库和集合驱动程序不能使用(它们会比 Flarum 内置的数据库搜索更差)。
以下是每个驱动程序的具体要求和配置。
虽然 Flarum 中只有讨论和用户可搜索,但此实现还使用了一个 posts
搜索索引,该索引以类似于 Flarum 原生搜索的方式与讨论搜索结果合并。当前讨论结果排序优先考虑最佳帖子匹配,因为我还没有找到合并讨论和帖子索引匹配分数的方法。
所有 Scout CLI 命令都可用,另外还有一个特殊的 "导入所有" 命令。
php flarum scout:import-all Import all Flarum models into the search index
(a shortcut to scout:import with every searchable class known to Flarum)
php flarum scout:flush {model} Flush all of the model's records from the index
php flarum scout:import {model} Import the given model into the search index
php flarum scout:index {name} Create an index (generally not needed)
php flarum scout:delete-index {name} Delete an index (generally not needed)
Algolia
Algolia 驱动程序需要在同名的云服务上有一个账户。
Meilisearch
Meilisearch 驱动程序需要一个正在运行的 Meilisearch 服务器实例。服务器可以托管在任何地方,只要它可以通过网络访问。默认情况下,扩展尝试连接到 127.0.0.1:7700
的服务器。
如果您没有运行最新的 Meilisearch 版本,您可能需要明确安装旧版本的 SDK。同样,如果您经常运行 composer update
来更新所有依赖项,您还应该在您的 composer.json
中添加对 Meilisearch SDK 的明确要求,因为扩展需要 *
,这可能会在新版本的 Meilisearch SDK 发布时跳转到较新版本。
要安装和锁定当前最新版本
composer require meilisearch/meilisearch-php
不幸的是,Meilisearch 似乎没有宣传与每个服务器版本兼容的特定 Composer 包版本。您可以在 https://packagist.org.cn/packages/meilisearch/meilisearch-php 找到发布列表。
一旦您知道需要哪个版本,您就可以将其锁定,例如安装旧版本的 0.23。
composer require meilisearch/meilisearch-php:"0.23.*"
Meilisearch 的唯一设置是 主机 和 密钥。其他一切都在 Meilisearch 服务器本身中进行配置。
即使您没有配置 默认结果限制 值并使用 Meilisearch,扩展也会自动将其设置为 200,因为 Meilisearch 的默认值(20)非常低,最多只能有 2 页的结果。
TNTSearch
TNTSearch 库需要 sqlite PHP 扩展,因此它默认不包含在 Scout 中。
要安装它,请确保您已为命令行和 web 服务器启用了 sqlite PHP 扩展,然后运行
composer require teamtnt/laravel-scout-tntsearch-driver
TNTSearch 使用本地 sqlite 数据库为每个索引。数据库存储在 <flarum>/storage/tntsearch
中,该目录必须可写。
以下设置被公开。每个设置的具体作用并不完全清楚,TNTSearch 的官方文档没有提供很多指导。
- 最大文档数:这可能会影响 Flarum 对查询能显示多少结果
- 模糊度(开启/关闭):看起来是用于错误拼写或变体匹配
- 模糊度 Levenshtein 距离
- 模糊度前缀长度:不知道它的作用
- 模糊度最大扩展:不知道它的作用
即时搜索 和 搜索布尔 被硬编码为启用,尽管它们在 TNTSearch 文档中描述的似乎不起作用。
安装
此扩展仍然是实验性的。请在测试服务器上先进行测试。我还没有亲自测试 Algolia,但从反馈来看,它似乎可以正常工作。
composer require clarkwinkelmann/flarum-ext-scout
支持的扩展和字段
此列表并不完整。如果您在扩展中添加了对 Scout 的支持,请告诉我,以便我可以更新此列表。
讨论
通过 Flarum 的搜索功能搜索讨论时,也会查询 帖子 字段。
- 标题:Scout 内置支持。
- Formulaire 讨论字段:自 Formulaire 1.8 起支持(仅限访客可访问的表单)。
帖子
- 内容:Scout 内置支持,使用的值是输出 HTML 的纯文本版本,不带任何标签。因此,一些信息(如链接 URL、图片 URL 和图片 alt 文本)不会被索引。这可能在未来的版本中改变。
用户
- 显示名称:Scout 内置支持。
- 用户名:Scout 内置支持。
- FoF 生物:Scout 内置支持(不在 FoF 生物本身中)。
- Formulaire 个人资料字段:自 Formulaire 1.8 起支持(仅限访客可访问的表单)。
Email 故意不提供搜索,因为目前还没有机制可以阻止普通用户使用此功能泄露电子邮件。
Formulaire
表单和提交可以选择通过 Scout 索引。有关详细信息,请参阅 Formulaire 文档。
开发者
扩展现有模型的搜索索引
使用扩展器注册您的属性,类似于扩展 Flarum 的序列化器。
此外,您应该注册一个在您的属性值更改时触发的事件监听器。
<?php use ClarkWinkelmann\Scout\Extend\Scout; use Acme\Event\SubtitleRenamed; return [ (new Scout(Discussion::class)) ->listenSaved(SubtitleRenamed::class, function (SubtitleRenamed $event) { return $event->discussion; }) ->attributes(function (Discussion $discussion): array { return [ 'subtitle' => $discussion->subtitle, ]; }), ];
如果注册事件监听器不是一个选项,您也可以在更改值后手动调用更新代码
<?php use ClarkWinkelmann\Scout\ScoutModelWrapper; use Flarum\Discussion\Discussion; /** * @var Discussion $discussion */ $discussion->subtitle = 'New value'; $discussion->save(); (new ScoutModelWrapper($discussion))->scoutObserverSaved();
如果您正在修改 Flarum 模型,而不是原始的存储/编辑/删除处理程序,别忘了触发 Flarum 事件(如讨论的 Started
和 Deleted
),以便 Scout 可以同步您的更改。
添加您自己的搜索引擎
任何扩展 Laravel\Scout\Engines\Engine
且与 Laravel Scout 一起工作的搜索引擎都应与此 Flarum 实现兼容。
目前没有扩展器可以将来自外部包的新引擎连接到 Scout。您可能需要通过分叉此扩展或使用容器绑定来覆盖 EngineManager
。
使您自己的模型可搜索
由于 Scout 可选且可扩展的约束,Scout 的模型配置和检索 API 与 Laravel 相比有许多变化。在可能的情况下,已保留类似名称的概念,即使它们现在通过扩展器或新全局方法发生。
由于无法在不使 Scout 成为要求的情况下将 Searchable
特性添加到 Flarum(或扩展)Eloquent 模型,因此未使用该特性。不要将 Searchable
特性添加到您的 Eloquent 模型中,即使您有能力编辑模型源代码!
本文档提到了两种模型,“真实”模型是Flarum或没有Searchable
特质的扩展的Eloquent模型,例如Flarum\User\User
。“包装”模型是本扩展的一个特殊功能,其中“真实”模型被包装在一个特殊的模型中,使其具有Searchable
能力。通常,“包装”模型将由该扩展在底层透明地使用,无需程序员进行任何特殊操作。如果您希望手动获取“包装”模型以调用其特定的Scout方法,可以使用new ScoutModelWrapper($model)
对其进行包装。
未使用内置的Scout模型观察者,而是使用Flarum事件来触发索引更新。
与Laravel的差异总结
Support/Eloquent集合方法与真实或包装模型的数组一起工作
Illuminate\Support\Collection::searchable()
:功能相同。Illuminate\Support\Collection::unsearchable()
:功能相同。
查询构建器方法/作用域在真实模型上工作
Eloquent\Builder::searchable()
:功能相同Eloquent\Builder::unsearchable()
:功能相同
Scout方法在真实模型上不可用,但所有有用的方法都有其他可调用的替代方式
Model::shouldBeSearchable()
:使用扩展器进行修改。Model::searchIndexShouldBeUpdated()
:不可定制。以后可能添加到扩展器中。Model::search()
:不可用。直接使用构建器。Model::makeAllSearchable()
:使用ScoutStatic::makeAllSearchable()
代替。Model::makeAllSearchableUsing()
:不可定制。以后可能添加到扩展器中。Model::searchable()
:不可用。手动在集合中包装或使用ScoutModelWrapper
调用。Model::removeAllFromSearch()
:使用ScoutStatic::removeAllFromSearch()
代替。Model::unsearchable()
:不可用。手动在集合中包装或使用ScoutModelWrapper
调用。Model::wasSearchableBeforeUpdate()
:不可定制。以后可能添加到扩展器中。Model::wasSearchableBeforeDelete()
:不可定制。以后可能添加到扩展器中。Model::getScoutModelsByIds()
:应该可以通过包装器使用,但建议不要使用。Model::queryScoutModelsByIds()
:应该可以通过包装器使用,但建议不要使用。Model::enableSearchSyncing()
:不可用。Model::disableSearchSyncing()
:不可用。Model::withoutSyncingToSearch()
:不可用。Model::searchableAs()
:不可定制。前缀可以在扩展设置中更改。Model::toSearchableArray()
:使用扩展器进行修改。Model::syncWithSearchUsing()
:不可定制。以后可能添加到扩展器中。Model::syncWithSearchUsingQueue()
:不可定制。以后可能添加到扩展器中。Model::pushSoftDeleteMetadata()
:不可用。Model::scoutMetadata()
:不可定制。以后可能添加到扩展器中。Model::withScoutMetadata()
:不可用。Model::getScoutKey()
:不可定制。以后可能添加到扩展器中。Model::getScoutKeyName()
:不可定制。以后可能添加到扩展器中。Model::usesSoftDelete()
:不可用。
不使用Scout::
静态对象
Laravel\Scout\Scout::$makeSearchableJob
:不可定制。Laravel\Scout\Scout::$removeFromSearchJob
:不可定制。Laravel\Scout\Scout::makeSearchableUsing()
:不可定制。Laravel\Scout\Scout::removeFromSearchUsing()
:不可定制。
提供了一个新的静态方法对象,不属于原始的Scout
ScoutStatic::makeAllSearchable(string $modelClass)
:触发给定类的索引或所有模型的索引。ScoutStatic::removeAllFromSearch(string $modelClass)
:触发给定类的去索引或所有模型的去索引。ScoutStatic::makeBuilder(string $modelClass, string $query, callable $callback = null)
:获取针对给定模型配置的Laravel\Scout\Builder
实例。
要使用侦察兵在代码中过滤结果,我建议忽略每个构建器/模型方法,并直接通过Scout Builder实例检索匹配的ID。
然后,您可以使用那个匹配ID的数组来修改Flarum搜索器(请参阅此扩展源代码中的帖子/用户搜索器)、过滤器或手动查询。
注意:ID数组将包含已删除和私有内容。请确保在查询中始终使用Flarum的whereVisibleTo()
。
为了保持搜索结果顺序,一个选项是使用FIELD()
SQL方法。如果您不进行分页,您还可以在从数据库检索结果后在PHP中重新排序结果。
<?php use ClarkWinkelmann\Scout\ScoutStatic; use Flarum\User\User; $builder = ScoutStatic::makeBuilder(User::class, 'Hello World'); $ids = $builder->keys(); $users = User::newQuery() ->whereVisibleTo($actor) ->whereIn('id', $ids) ->orderByRaw('FIELD(id' . str_repeat(', ?', count($ids)) . ')', $ids) ->limit(10) ->get();
支持
此扩展处于最小维护状态。
它是为某个客户开发的,并作为开源软件发布,以造福社区。我可能会免费发布简单的错误修复或兼容性更新。
您可以联系我赞助额外功能或更新。
支持通过Flarum社区线程提供,基于“尽力而为”原则。