ホームページ > バックエンド開発 > PHPチュートリアル > PINQ-データセットを照会 - ファセット検索

PINQ-データセットを照会 - ファセット検索

Lisa Kudrow
リリース: 2025-02-20 12:29:14
オリジナル
559 人が閲覧しました

PINQ-データセットを照会 - ファセット検索

キーテイクアウト

    PHP LINQポートであるPINQを使用して、MySQLを使用してファセット検索機能を模倣して、強力で率直なアプローチを提供します。
  • ユーザーが提供するキーワードを使用して製品を検索し、一致する製品を返し、さまざまなブランド、価格帯、機能に基づいて検索を微調整するためのリンクを提供することにより、ファセット検索が機能します。
  • PINQを使用して、$範囲で指定されたステップの値範囲でグループ化するなど、必須ファセット検索機能を追加することにより、デモアプリケーションを拡張できます。
  • PINQで実装されたファセット検索は、毎回MySQLサーバーからデータを取得します。これは、キャッシュエンジンを使用することで回避できます。
  • 基本的なデモであるにもかかわらず、ファセット検索に対するPINQのアプローチは、改善の余地を十分に提供し、より高度なユースケースのために構築できます。
  • パート1では、PHP LINQポートであるPINQのインストールと基本的な構文を簡単にカバーしました。この記事では、PINQを使用してファセット検索機能をMySQLで模倣する方法を確認します。
  • このシリーズでは、ファセット検索の完全な側面をカバーするつもりはありません。利害関係者は、SitePointやその他のインターネット出版物で公開されている関連記事を参照できます。
  • 典型的なファセット検索は、ウェブサイトでこのように機能します:
ユーザーは、キーワードまたはいくつかのキーワードを提供します。たとえば、説明、キーワード、カテゴリ、タグなどに「ルーター」を含む製品を検索する「ルーター」

サイトは、基準に一致する製品を返します

このサイトは、検索を微調整するためのリンクを提供します。たとえば、ルーターにはさまざまなブランドがあることを促す場合があり、さまざまな価格帯とさまざまな機能がある場合があります。

ユーザーは、提供されたさまざまなリンクをクリックして結果をさらにスクリーニングでき、最終的にはよりカスタマイズされた結果セットを取得できます。

  • ファセット検索は非常に人気があり、強力であり、ほぼすべてのeコマースサイトで体験できます。
  • 残念ながら、ファセット検索はMySQLが提供する組み込み機能ではありません。 MySQLを使用しているだけでなく、ユーザーにそのような機能を提供したい場合はどうすればよいですか?
  • PINQを使用すると、他のDBエンジンを使用しているとき、少なくともある意味でこれを達成するための同様に強力で率直なアプローチがあることがわかります。 パート1デモ
  • の拡張
  • 注:このパートとパート1のデモのすべてのコードは、リポジトリにあります。
  • この記事では、パート1に示したデモを拡張し、いくつかの重要なファセット検索機能を追加します。

以下の数行を追加して、index.phpから始めましょう:

デモアプリケーション(Silexを使用)でさらに2つのルートを作成しました。

最初のルートは、最初の検索動作に一致するすべてのレコード、つまりキーワードを提供して検索を示すすべてのレコードを表示するページに私たちを連れて行くことです。デモをシンプルに保つために、サンプルbook_bookテーブルからすべての本を選択します。また、さらにナビゲーションのための結果セットとファセットリンクも表示されます。

2番目のルートでは、上記のステップで作成された結果セットのさらにファセット検索基準に一致するレコードを示す別のページにもたらされます。ファセットの検索リンクも表示されます。

現実世界の実装では、ファセットリンクがクリックされた後、結果ページのファセットフィルタリングは、結果データセットの統計情報を反映するように調整されます。これを行うことにより、ユーザーは「アドオン」上映を適用し、最初に「ブランド」を追加してから「価格帯」などを追加できます。

しかし、この単純なデモでは、このアプローチをスキップします。すべてのファセット検索とリンクは、元のデータセットの情報のみを反映します。これは最初の制限であり、デモの改善のための最初の領域です。

上記のコードからわかるように、実際の関数はpinqdemo.phpという別のファイルにあります。ファセット検索機能を提供する関連コードを見てみましょう。

ファセットクラス

最初に、ファセットを表すクラスを作成します。一般的に、ファセットにはいくつかのプロパティが必要です:

それが動作するデータ($ data)

    ($ key)
  • でグループ化するキーグループ
  • キータイプ($タイプ)。それは以下の1つである可能性があります:
  • 完全な一致を作成するために完全な文字列を指定します
      パターンの一致を作成するために、文字列の部分的な(通常は始まり)
    • を指​​定します
    • 値範囲でグループへの値範囲を指定
    • キータイプが範囲の場合、範囲の上部/下限を決定するための値ステップを指定する必要があります。または、キータイプが部分的な文字列である場合、グループ($範囲)
  • グループは、ファセットで最も重要な部分です。ファセットが返す可能性があるすべての集約情報は、「グループ化」基準によって異なります。通常、「フル文字列」、「部分文字列」、「値範囲」が最も一般的に使用されるものです。
  • このクラスでは、重要な関数は、データとファセットキープロパティに基づいてファセット結果セットを返すことです。さまざまな種類のキーについて、データをグループ化するさまざまな方法があることに気付きました。上記では、$範囲で指定されたステップの値範囲でデータをグループ化する場合、コードがどのように見えるかを示しました。
ファセットを作成し、元のデータを表示します

<span>$app->get('demo2', function () use ($app)
</span><span>{
</span>    <span>global $demo;
</span>    <span>$test2 = new pinqDemo<span>\Demo</span>($app);
</span>    <span>return $test2->test2($app, $demo->test1($app));
</span><span>}
</span><span>);
</span>
<span>$app->get('demo2/facet/{key}/{value}', function ($key, $value) use ($app)
</span><span>{
</span>    <span>global $demo;
</span>    <span>$test3 = new pinqDemo<span>\Demo</span>($app);
</span>    <span>return $test3->test3($app, $demo->test1($app), $key, $value);
</span><span>}
</span><span>);</span>
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
getFacet()関数では、次の手順を実行します
  • 元のデータをPinQTrabules可能なオブジェクトに変換して、さらに処理します。
  • 3つのファセットを作成します。 「著者」ファセットはフィールド著者にグループ化され、完全な文字列グループです。フィールドタイトルの「タイトル」ファセットと部分的な文字列グループ(開始6文字カウント)。フィールド価格と範囲グループの「価格」ファセット(10段階)。
  • 最後に、ファセットを取得し、テンプレートがデータとファセットをレンダリングできるようにTest2関数に戻します。
  • ファセットとフィルター処理されたデータの表示
ほとんどの場合、ファセットはリンクとして表示され、フィルター処理されたデータセットに表示されます。

既にルート( 'demo2/facet/{key}/{value}')を作成して、ファセット検索結果とファセットリンクを表示しています。

ルートには2つのパラメーターがあり、ファセットのキーとそのキーの値を反映しています。最終的にそのルートから呼び出されるtest3関数は、以下の抜粋を次のようにしています。

基本的に、キーに応じて、渡された値に対応するフィルタリング(句の匿名関数)を適用し、さらにスクリーニングされたデータを取得します。ファセットデータの順序を指定することもできます。

最後に、テンプレートにデータ(ファセットとともに)を表示します。このルートは、ルート「Demo2」で使用されるテンプレートと同じテンプレートをレンダリングします。
<span>$app->get('demo2', function () use ($app)
</span><span>{
</span>    <span>global $demo;
</span>    <span>$test2 = new pinqDemo<span>\Demo</span>($app);
</span>    <span>return $test2->test2($app, $demo->test1($app));
</span><span>}
</span><span>);
</span>
<span>$app->get('demo2/facet/{key}/{value}', function ($key, $value) use ($app)
</span><span>{
</span>    <span>global $demo;
</span>    <span>$test3 = new pinqDemo<span>\Demo</span>($app);
</span>    <span>return $test3->test3($app, $demo->test1($app), $key, $value);
</span><span>}
</span><span>);</span>
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
次に、テンプレートを見て、ファセットリンクがどのように表示されるかを見てみましょう。私はBootstrapを使用しているので、ここで使用するCSSコンポーネントは非常に馴染みがあるはずです:

アプリによって生成されたファセットはネストされた配列であることを覚えておく必要があります。最初のレイヤーでは、すべてのファセットの配列であり、私たちの場合、合計3つ(著者、タイトル、著者の場合)があります。

各ファセットの場合、それは「キー価値」のペアな配列であり、従来の方法で反復することができます。

<span>namespace classFacet
</span><span>{
</span>    <span>use Pinq<span>\ITraversable</span>,
</span>        Pinq\Traversable<span>;
</span>
    <span>class Facet
</span>    <span>{
</span>
        <span>public $data; // Original data
</span>        <span>public $key; // the field to be grouped on
</span>        <span>public $type; // F: full string; S: start of a string; R: range;
</span>        <span>public $range; // Only valid if $type is not F
</span>
		<span>...
</span>
        <span>public function getFacet()
</span>        <span>{
</span>            <span>$filter = '';
</span>
            <span>if ($this->type == 'F') // Full string 
</span>            <span>{
</span>				<span>...
</span>            <span>}
</span>            <span>elseif ($this->type == "S") //Start of string
</span>            <span>{
</span>				<span>...
</span>            <span>}
</span>            <span>elseif ($this->type == "R") // A value range
</span>            <span>{
</span>                <span>$filter = $this->data
</span>                        <span>->groupBy(function($row)
</span>                        <span>{
</span>                            <span>return floor($row[$this->key] / $this->range) * $this->range;
</span>                        <span>})
</span>                        <span>->select(function (ITraversable $data)
</span>                <span>{
</span>                    <span>return ['key' => $data->last()[$this->key], 'count' => $data->count()];
</span>                <span>});
</span>            <span>}
</span>
            <span>return $filter;
</span>        <span>}
</span>    <span>}
</span><span>}</span>
ログイン後にコピー
ログイン後にコピー
リンクのurisをどのように構築するかに注意してください。外側のループのキー(k)と内側のループキー(vv.key)の両方をルート( 'demo2/facet/{key}/{value}')のパラメーターにしました。キー(vv.count)のカウントは、テンプレート内のディスプレイ(ブートストラップバッジとして)のタッチアップに使用されます。

テンプレートは、以下に示すようにレンダリングされます:

(最初のエントリページは、$ 0から10ドル、著者が注文した価格のファセット結果を示しています)PINQ-データセットを照会 - ファセット検索
大丈夫、これまでのところ、Webアプリのファセット検索機能を模倣することができました! このシリーズを締めくくる前に、このデモを最後に見て、それを改善するために何ができるか、何が制限となっているかを確認します。 PINQ-データセットを照会 - ファセット検索

改善が行われる

全体として、これは非常に初歩的なデモです。基本的な構文と概念を駆け抜けて、それらを実行できる例に偽造しました。先ほど見たように、いくつかの領域を改善して柔軟性を高めることができます。

「アドオン」基準検索機能を提供することを検討する必要があります。現在の実装は、スクリーン型のデータではなく、元のみに適用されるファセット検索を制限します。これは私が考えることができる最も重要な改善です。

制限

ここに実装されているファセット検索には、根深い制限があります(おそらく他のファセット検索の実装に当てはまります):

毎回mysqlサーバーからデータを取得しています。

このアプリは、Silexをフレームワークとして使用します。 Silex、Symfony、Laravel、Index.php(またはapp.php)などの単一の突入フレームワークの場合、ルートを分析し、コントローラーの関数を呼び出すたびに呼び出されます。

index.phpのコードを見ると、これは以下のコードの行も意味することがわかります:

<span>$app->get('demo2', function () use ($app)
</span><span>{
</span>    <span>global $demo;
</span>    <span>$test2 = new pinqDemo<span>\Demo</span>($app);
</span>    <span>return $test2->test2($app, $demo->test1($app));
</span><span>}
</span><span>);
</span>
<span>$app->get('demo2/facet/{key}/{value}', function ($key, $value) use ($app)
</span><span>{
</span>    <span>global $demo;
</span>    <span>$test3 = new pinqDemo<span>\Demo</span>($app);
</span>    <span>return $test3->test3($app, $demo->test1($app), $key, $value);
</span><span>}
</span><span>);</span>
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
アプリ内のページが表示されるたびに呼び出されます。これは、次の行が毎回実行されることを意味します。

フレームワークの使用を避ける方が良いでしょうか?まあ、フレームワークなしでアプリを開発することは本当にそれほど良い考えではないという事実に加えて、私たちはまだ同じ問題に直面しています。データ(およびステータス)は、HTTPコールから別の呼び出しまで永続的ではありません。これがHTTPの基本的な特性です。これは、キャッシュエンジンを使用することで避ける必要があります。
<span>namespace classFacet
</span><span>{
</span>    <span>use Pinq<span>\ITraversable</span>,
</span>        Pinq\Traversable<span>;
</span>
    <span>class Facet
</span>    <span>{
</span>
        <span>public $data; // Original data
</span>        <span>public $key; // the field to be grouped on
</span>        <span>public $type; // F: full string; S: start of a string; R: range;
</span>        <span>public $range; // Only valid if $type is not F
</span>
		<span>...
</span>
        <span>public function getFacet()
</span>        <span>{
</span>            <span>$filter = '';
</span>
            <span>if ($this->type == 'F') // Full string 
</span>            <span>{
</span>				<span>...
</span>            <span>}
</span>            <span>elseif ($this->type == "S") //Start of string
</span>            <span>{
</span>				<span>...
</span>            <span>}
</span>            <span>elseif ($this->type == "R") // A value range
</span>            <span>{
</span>                <span>$filter = $this->data
</span>                        <span>->groupBy(function($row)
</span>                        <span>{
</span>                            <span>return floor($row[$this->key] / $this->range) * $this->range;
</span>                        <span>})
</span>                        <span>->select(function (ITraversable $data)
</span>                <span>{
</span>                    <span>return ['key' => $data->last()[$this->key], 'count' => $data->count()];
</span>                <span>});
</span>            <span>}
</span>
            <span>return $filter;
</span>        <span>}
</span>    <span>}
</span><span>}</span>
ログイン後にコピー
ログイン後にコピー
ファセットを構築しているときにサーバー側で実行されるいくつかのSQLステートメントを保存します。同じステートメントのクエリで1つの選択クエリと3つの異なるグループを渡す代わりに、whereステートメントで1つの選択クエリを発行し、PINQを使用して集約情報を提供します。

結論

この部分では、本のコレクションサイトのファセット検索機能を模倣することができました。私が言ったように、それは単なる缶のデモであり、改善の余地がたくさんあり、いくつかのデフォルトの制限があります。この例に基づいて構築し、さらに高度なユースケースを表示できる場合はお知らせください!

PINQの著者は、次のメジャーバージョンリリース(バージョン3)に取り組んでいます。私はそれがより強力になることを願っています。

あなたのコメントや考えを下に残してください!

PINQとファセット検索に関するよくある質問(FAQ)

PINQとは何ですか、それはファセット検索とどのように関係していますか?

PINQは、配列やその他のデータセットを操作するためのユニークで直感的で強力なクエリ言語を提供するPHPライブラリです。データのクエリと操作のプロセスを簡素化するように設計されています。ファセット検索に関連して、PINQを使用して、ファセット検索のコア概念である複数の基準に基づいてデータをフィルタリングおよびソートできる複雑なクエリを作成できます。

ファセット検索に対するPINQのアプローチは、他の方法とどのように異なりますか?

ファセット検索に対するPINQのアプローチは、広く使用されているプログラミング言語であるPHPに基づくクエリ言語を使用するため、ユニークです。これにより、PHPにすでに精通している開発者がファセット検索を実装しやすくなります。さらに、PINQのクエリ言語は直感的で使いやすいように設計されており、複雑なクエリを作成するプロセスを簡素化できます。 > PINQはMySQLに限定されません。配列やその他のデータベースなど、任意のデータセットで使用できます。この柔軟性により、PINQはさまざまな種類のデータを操作する必要がある開発者にとって汎用性の高いツールになります。これは、怠zyな評価戦略を使用して行います。つまり、実際に必要な場合にのみデータを処理することを意味します。これにより、大規模なデータセットを操作するときにパフォーマンスが大幅に向上します。

ファセット検索にPINQを使用することの利点は何ですか?まず、複雑なクエリを作成するプロセスを簡素化し、開発者の時間と労力を節約できます。第二に、幅広いデータ型と構造を処理できる強力で柔軟なクエリ言語を提供します。最後に、これは広く使用されているプログラミング言語であるPHPに基づいているため、開発者が学習と使用を容易にします。 PINQは直感的で使いやすいように設計されており、初心者と経験豊富な開発者の両方に適しています。ただし、PINQを使用する場合、PHPとクエリ言語の知識は有益です。

検索結果の精度をどのように保証しますか?

PINQは、強力で柔軟性を使用して検索結果の精度を保証します。複数の基準に基づいてデータを正確にフィルタリングおよびソートできる言語をクエリします。これにより、正確で関連性のある検索結果を提供できます。

PINQをリアルタイム検索に使用できますか?大規模なデータセットの効率的な取り扱いと複雑なクエリを作成する機能により、リアルタイム検索アプリケーションに適しています。

ファセット検索の他のPHPライブラリと比較して?ユニークで直感的で強力なクエリ言語のために、ファセット検索のための他のPHPライブラリから外出しています。また、処理できるデータの種類の観点から柔軟性を提供し、大規模なデータセットの効率的な取り扱いにより、開発者にとって強い選択肢になります。

はい、PINQはオープンソースライブラリです。つまり、開発者は特定のニーズに合わせてカスタマイズできます。この柔軟性は、ファセット検索にPINQを使用するもう1つの利点です。

以上がPINQ-データセットを照会 - ファセット検索の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート