Show HN: PHP-fts ― 拡張機能を使用しない純粋な PHP で実装された全文検索エンジンです。

2026/05/07 5:28

Show HN: PHP-fts ― 拡張機能を使用しない純粋な PHP で実装された全文検索エンジンです。

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

php-fts は、共有ホストおよび小規模な VPS 環境に特化して設計された軽量で純粋な PHP(v8.1+)フルテキスト検索エンジンであり、外部サービスまたは複雑なデータベースの必要性を排除します。業界標準の BM25 + IDF スコアリング、フィールドブースティング、バイナリファイルストレージを活用し、数枚から数万件のドキュメント規模のデータセットをサポートします。Linux 共有ホストでのパフォーマンステストでは、1 万件のドキュメントに対する平均レイテンシーが 3.2 ミリ秒であることを示しており、単一ロックによるバッチ挿入は個別レコード insertion の速度の約 2 倍です。このエンジンには、Composer または手動インストールを通じてランク付けされた結果を提供する機能があり、トムストーンを用いたソフトデリート、原子更新、コンパクト化などの高度な機能を備えています。堅牢なフィルタリングロジックにより、AND/OR オペレーター、完全一致、範囲指定、

in
/
not in
チェック、配列
contains
のようなフィルタリングがサポートされます。OVH や Infomaniak などのプロバイダーやリソース制約のある環境での最適化を意図してはいますが、数百万件のドキュメントへのスケーリングや大量のリアルタイム同時書き込みの処理には使用することを想定していません。

本文

純粋な PHP で実装された、完全自律型のフルテキスト検索エンジンです。 拡張機能を使わず、外部サービスや依存関係を一切必要とせず、単なるファイルのみで動作します。

このツールは誰のためのものか?

php-fts
は、専用検索サービスの導入が不可能なプロジェクト向けに設計されています(共有ホスティング、小規模な VPS、あるいはスタックの最小化とポータビリティを重視する状況など)。

Elasticsearch、Meilisearch、または Typesense を利用し、それらを運用するためのインフラをお持ちであれば、そちらのご利用をお勧めします。これらはより高性能であり、高トラフィックや大規模ワークロードのために構築されたものです。 しかし、そのような環境がない場合、あるいはあえてそう選ばれるのであれば、

php-fts
はインストールする必要がなく、ディレクトリのパス設定以外の設定も不要というシンプルさの中で、ソート機能付き、フィルター対応、および誤変換にも強いマッチング機能を実現する堅牢なフルテキスト検索を提供します。

適している場合

  • 共有ホスティング環境上にある場合(OVH、Infomaniak、o2switch など)
  • インフラストラクチャへのオーバーヘッドをゼロにしたい場合
  • データセットの規模が数百から数万のドキュメントの場合
  • オフラインまたはスケジュールに基づいてインデックスを更新し、ランタイムで検索を実行する場合

適さない場合

  • 高負荷な並行書込み下でのリアルタイムインデックスが必要である場合
  • データセットの規模が数百万のドキュメントにある場合
  • ジオ位置検索やマルチテナント対応を必要とする場合

機能

  • 三語素(トリグラム)インデックス付きフルテキスト検索 — 誤字脱字や部分一致にも耐性があります。
  • BM25 + IDF スコアリング — 業界標準の関連性ランキングアルゴリズム(Lucene / Elasticsearch と同一)。
  • ドキュメントごとのスコア暴露 — レスポンズ内に公開され、ファセットカウント、ソート、または独自ランキング構築に利用可能です。
  • フィールドブースティング — タイトルなど特定のフィールドを他のフィールドよりも重み付けできます。
  • フィルター機能 — 完全一致、比較演算子、範囲指定、配列フィールドへの
    in
    not in
    contains
    などが可能。
  • 複合 AND/OR フィルタリング — フレキシブルな条件ロジックが可能です。
  • バッチ挿入(Bulk insertion) — 単一挿入と比較して最大約 2.4 倍高速化。全体に対して单一ロックで処理されます。
  • グラブストーン方式のソフト削除 — 高速な削除が可能で、コンパクション時に不要なデータがクリーニングされます。
  • 原子更新 — ソフト削除と再挿入を單一ロックで一度に実行できます。
  • コンパクション機能 — インデックスファイルをクリーンに再構築し、削除されたドキュメントを除去します。
  • フラグメンテーションモニタリング — コンパクションを行うべきタイミングが把握できます。
  • バイナリファイル形式のストレージ — サーバー間での移行が可能で、再構築は不要です。
  • O(1) 三語素.Lookup — 固定サイズインデックス(約 810 KB)を使用し、木構造の探索は不要です。
  • 拡張機能不要 — 標準搭載の PHP 8.1 以上で動作します。

要件

  • PHP 8.1 またそれ以降
  • インデックスファイル用のディレクトリへの読み書きアクセス権限

インストール

Composer を経由して

composer require ols/php-fts

ハンドインストール(Composer を使用しない場合)

src/
ディレクトリをプロジェクト内にコピーし、_autoload.php_を読み込みます:

require '/path/to/php-fts/src/autoload.php';

クイックスタート

use Ols\PhpFts\SearchEngine;

$engine = new SearchEngine();
$engine->open('./search_data');

// ドキュメントの挿入
$docId = $engine->insert([
    'title'       => 'Brown leather shoe',
    'description' => 'Elegant city shoe in soft leather',
    'price'       => 129.90,
    'stock'       => 42,
    'active'      => true,
    'category'    => 'Shoes',
    'brand'       => 'Adidas',
    'tags'        => ['summer', 'luxury', 'city'],
]);

// 検索実行
$results = $engine->search('leather shoe', limit: 20, boosts: [
    'title'       => 3.0,
    'description' => 1.0,
]);

foreach ($results as $result) {
    echo $result['document']['title'] . ' — score: ' . $result['score'] . PHP_EOL;
}

$engine->close();

API リファレンス

オープン / クローズ

$engine->open('./search_data');   // ディレクトリやファイルが存在しない場合は作成します
$engine->close();                 // ファイルハンドルのフラッシュとクローズを実行します

挿入 (Insert)

// 単一のドキュメント — ドキュメント ID(バイナリオフセット)を返します。更新や削除が必要な場合はこれを保持してください。
$docId = $engine->insert([
    'title'  => 'My product',
    'price'  => 49.90,
    'active' => true,
    'tags'   => ['new', 'sale'],
]);

// バッチ挿入 — 全体に対して單一ロックで処理されるため、大幅に高速化します。
$docIds = $engine->insertBulk([
    ['title' => 'Product A', 'price' => 29.90],
    ['title' => 'Product B', 'price' => 59.90],
]);

// サポートされているフィールドタイプ:string, int, float, bool, string の配列。

検索 (Search)

$results = $engine->search(
    query:         'leather shoe',
    limit:         20,
    maxCandidates: 5000,
    boosts:        ['title' => 3.0, 'description' => 1.0],
    filters:       [...],
);

// 各結果の構造:
[
    'docId'    => 942222,   // ドキュメント識別子
    'score'    => 43.74,    // BM25+IDF 関連性スコア(0-100 の範囲)
    'document' => [...],    // オリジナルのドキュメント配列
]

// score フィールドはすべての結果にあり、ファセットカウント、独自ソート、または関連性閾値の設定などに利用できます。

フィルター (Filters)

$results = $engine->search('shoe', filters: [

    'and' => [
        ['field' => 'active',   'op' => '=',        'value' => true],
        ['field' => 'stock',    'op' => '>',         'value' => 0],
        ['field' => 'price',    'op' => '<=',        'value' => 300],
        ['field' => 'category', 'op' => 'in',        'value' => ['Shoes', 'Sport']],
        ['field' => 'tags',     'op' => 'contains',  'value' => 'luxury'],
    ],

    'or' => [
        ['field' => 'brand', 'op' => '=', 'value' => 'Adidas'],
        ['field' => 'brand', 'op' => '=', 'value' => 'Puma'],
    ],

]);

// "and" と "or" の両方は任意ですが、少なくとも片方は指定する必要があります。
// 両方を併用する場合は、すべての AND 条件が満たされ、かつ少なくとも一つの OR 条件も満たされる必要があります。
// フィルター対象のフィールドが存在しないドキュメントは結果から除外されます。

// 演算子とサポートされているタイプ:
/*
  =      | int, float, bool, string
  !=     | 
  > >= < <=    | int, float
  in not in   | int, float, string
  contains not contains  | array (ドキュメントのフィールドに対して)
*/

更新 / 削除 (Update / Delete)

// 原子更新:单一ロック内でソフト削除と再挿入を実行します。
$newDocId = $engine->update($docId, ['title' => 'Updated title', 'price' => 149.90]);

// ソフト削除(コンパクション時にクリーニングされます)
$engine->delete($docId);

メンテナンス (Maintenance)

$count = $engine->count();               // ライブドキュメント数
$rate  = $engine->fragmentationRate();   // フラグメンテーション率(0 がクリーン、100 が全削除状態)

if ($engine->fragmentationRate() > 20) {
    $engine->compact();                  // インデックスファイルを再構築し、削除されたドキュメントを除去します
}

$engine->reset();                        // すべてのインデックスファイルを消去し、新しく開始します

インデックスファイル構成

search_data/
  documents.bin    — シリアライズされたドキュメント(JSON とバイナリ形式のハイブリッド)
  trigrams.bin     — 固定サイズ三語素インデックス(約 810 KB、37^3 エントリー、O(1) アクセス)
  postings.bin     — 各三語素ごとの doc_id リスト
  tombstones.bin   — 削除された doc_id(コンパクション時にクリアされる)

ファイルは完全にポータブルです。サーバー間でコピーし直すだけで再構築不要です。

スコアリング (Scoring)

関連性の計算には BM25 + IDF が使用されます:

  • BM25 — 用語頻度の飽和効果(10 回出現してもスコアが 10 倍になるわけではない)およびドキュメント長正規化を採用。パラメータ:k1 = 1.5、b = 0.75(標準的な Lucene のデフォルト値)。
  • IDF — すべてのドキュメントに含まれる三語素は寄与が小さく、稀な三語素は大きく寄与します。
  • 最終スコアは 0 から 100 の範囲で正規化されます。

ベンチマークテスト

ベンチマークは以下の 2 つの環境で実施されました:

  • Windows 11 — ローカルマシン、NVMe SSD、PHP 8.3
  • Linux(OVH 共有ホスティング) — 標準共有プラン、PHP 8.3

インサージョン性能

Volumeinsert() Windowsinsert() LinuxinsertBulk() WindowsinsertBulk() Linux
1,0005.3 s7.3 s3.0 s3.0 s
5,00033.5 s14.8 s
10,00053.0 s63.4 s30.5 s29.4 s
50,000282.2 s157.8 s

インサージョンはオフライン作業であり、通常はスCHEDULED JOB(定時タスク)経由で行われ、リクエスト時に実行されません。 本番環境では常に

insertBulk()
を優先してください。全体に対して單一ロックを取得し、一貫して約 2 倍高速になります。

インデックスサイズ

VolumeIndex size
1,0002.8 MB
10,00021.7 MB
50,000106.0 MB

検索性能(Linux 共有ホスティング、10,000 ドキュメント)

MetricValue
Median3.2 ms
Average4.9 ms
P9512.5 ms
P9922.9 ms
Min / Max1.3 ms / 37.1 ms

測定条件:200 クエリ、10 の異なるクエリをローテーション(誤字脱字やコーパス外検索を含む)。通常の負荷下で、実稼働中の共有ホスティング環境にて

hrtime()
を使用して測定。

例示アプリケーション

以下の GIF は、

php-fts
の一つの使用例を示しています——フィルター付きソート可能な結果を表示する製品検索インターフェース(架空の履物カタログの上層ビルド)。 これは単なる例示であり、
php-fts
はエンジンそのものでありインターフェースではありません。製品検索、文書検索、管理画面フィルター、CLI ツール、あるいは特定のドキュメントセットに対するフルテキストマッチングが求められるあらゆる用途にご活用いただけます。

ローカルで実行するには:

php demo/seed.php
php -S localhost:8000 -t demo

データベースなし、外部サービスなし。フィルター、スコア、結果件数などはすべてエンジン内で計算されます。

ライセンス

MIT ライセンス —

LICENSE
ファイルをご覧ください。

同じ日のほかのニュース

一覧に戻る →

2026/05/07 0:44

Valve が、クリエイティブ・コモンズライセンスの下で、Steam Controller のCAD ファイルを公開しました。

## Japanese Translation: Valve は、Steam コントローラーと Puck の CAD ファイルを正式に公開し、マッダーがスキン、グリップエクステンダー、充電スタンド、スマートフォン用マウントなどの追加機能を作成できるようにしました。このパッケージには、内部シェル(外観の表面トポロジー)のみをカバーする .STP、.STL およびエンジニアリング図面ファイルが含まれており、信号強度とデバイスの機能性を維持するため、特定の内側領域は除外されています。このリリースは、Steam Deck、Valve Index、および元々の Steam コントローラーで確立された Valve のデザインオープン哲学を継承するものです。 ファイルは、非営利利用を義務付け、出典の明記を要求し、派生作品をコミュニティに還元することを義務付ける制限付きクリエイティブ・コモンズライセンスの下で配布されています。アクセサリを製造したい商業組織は、代わりに Valve に直接連絡して特定の手続を交渉する必要があります。マッダーは外表面において自由なイノベーションが可能ですが(例:Moonlight を通じて *Forza Horizon 6* などのストリーミングタイトル用にスマートフォン用クリップを設計する場合など)、エンジニアリング図面で示されるように、適正な動作を保証するために被覆を維持すべき領域については制限も明確化されています。全体として、これはコミュニティのイノベーションを育む活発なエコシステムを促進しつつ、コアハードウェア保護を維持し、信号強度や内部操作を損なうことなく協力のための明確な経路を定義するものです。

2026/05/07 8:04

DeepSeek V4 Pro:5 月 31 日までの 75%オフ特別セール開催中

## Japanese Translation: 2026 年 4 月 26 日より、DeepSeek は v4 モデルを大規模にアップデートし、OpenAI または Anthropic API フォーマット(`https://api.deepseek.com` および `https://api.deepseek.com/anthropic`)で利用可能な新しい価格設定および技術機能を導入することを発表しました。課金は 1M トークン(入力 + 出力)あたりで行われ、トークンは文字を認識する最小単位を表します。 主要な価格改定は以下の通りです: - **deepseek-v4-flash**: 入力のキャッシュヒットが $0.0028/M、キャッシュミスが $0.14/M、出力が $0.28/M です。 - **deepseek-v4-pro**: `pro` モデルの入力および出力コストは、2026 年 5 月 31 日まで 75% 削減されます(入力キャッシュヒットは元の $0.0173/M 相当から現在 $0.0145/M に、入力キャッシュミスは元の $0.0200/M 相当から現在 $1.74/M に、出力は現在 $0.87/M に)。さらに、2026 年 4 月 26 日 UTC 12:15 から、すべてのモデルの入力キャッシュヒット価格はローンチ価格の 1/10 に引き下げられます。 技術仕様: - `flash` および `pro` の両モデルでコンテキスト長は 1M トークンに対応し、最大出力トークン制限は 384K です。 - **deepseek-v4-flash** は、デフォルトの非思考モードと thinking モード(それぞれ廃止された名称 `deepseek-chat` および `deepseek-reasoner` に対応)を両方提供します。**deepseek-v4-pro** は現在、非思考モードのみで稼働しています。 - 機能には JSON 出力、ツール呼び出し、チャットプレフィックス補完(Beta)、FIM 補完(Beta)が含まれます。 課金はまず追加された残高から引き落としされ、かつ残高が存在する場合でもその順序に従って引き落とします。これらの変更はコスト削減と開発者向けの柔軟なデプロイオプションの提供を目指しています。

2026/05/07 1:18

職場において生産的な姿を示すこと

## Japanese Translation: 記事は、パークインソンの法則を AI に適用することによって、「出力と能力の乖離」という危険な状態が生じると警告しています。これは、生成ツールが制限のないことで、技能不足な労働者が高品質に見えながら欠陥のある成果物を生み出せることを意味します。初心者が上級レベルの作業を作成したり、訓練を受けていない分野の成果物を生成したりすることができます。特に、エンジニアでない人がソフトウェアを構築したりデータシステムを設計したりといった横断領域のタスクにおいてはそのリスクが高まります。大多数の此类の成果物は外部に提供されず、むしろ長時間の過労と機構的な慣性の下で内部に蓄積されていきます。証拠として挙げられるのは、VP の支援にもかかわらず、根本から間違ったシステムを 2 ヵ月かけて構築した非エンジニアの同僚に関する事例で、これが勢いが現実に優先する様子を示しています。研究もこれらのリスクを確認しており、Cheng ら(Science)は先導的モデルが人間よりも約 50% アグリーブルであると発見しており、Berkeley CMR のメタ解析では AI リテラシーを持つユーザーが自己の性能を過大評価していることを示し、NBER の研究では生成型 AI が新人の生産性を約 3 分の 1 向上させた一方、専門家にはほとんど貢献しておらず、Harvard Business School の研究ではレビューできない分野でコンサルティングの新人が個別の生産性を獲得したことを示しています。論文の長さは約 1 ページから約 12 ページへと延伸し、生成コストがほぼゼロとなった一方で、読取コストは人工的な文脈を上回っています。実際の世界的な影響には、AI の幻覚による政府報告書が発端となり、Deloitte が手数料の一部を返金した事件があり、これは企業が AI の誤用によって空洞化されると、最終的にはクライアントが支払った核心価値を失うことになるという警告を含んでいます。専門家は、これらのツールを判断が求められるタスクに使用することや、速いフィードバックを得られる活動(ブレインストーミング、校正、アイデアの再定式化、パターン検出など)に限定することを推奨しており、ここで人間は判断を提供し、ツールはthroughput を提供するとしています。時間の無駄とクライアントからの返金を起因とする著しい財務損失を避けるため、組織は人工的な文脈と事実に厳密に区別し、重要な意思決定を徹底的に人間の監督下においておくことが緊急に必要です。

Show HN: PHP-fts ― 拡張機能を使用しない純粋な PHP で実装された全文検索エンジンです。 | そっか~ニュース