首页 > 后端开发 > php教程 > PINQ-查询数据集 - 面式搜索

PINQ-查询数据集 - 面式搜索

Lisa Kudrow
发布: 2025-02-20 12:29:14
原创
560 人浏览过

PINQ-查询数据集 - 面式搜索

钥匙要点

    PHP LINQ端口
  • pinq可以用MySQL模仿刻面搜索功能,提供强大而直接的方法。
  • >通过使用用户提供的关键字来搜索产品,返回匹配的产品以及提供基于不同品牌,价格范围和功能的搜索的链接来搜索产品。
  • > PINQ可以通过添加基本的搜索功能来扩展演示应用程序,例如在$范围指定的步骤中按值分组。
  • >每次使用pinq检索数据的刻面搜索都可以从MySQL Server检索数据,可以通过使用缓存引擎来避免。 尽管是基本的演示,但Pinq的Facet搜索方法提供了足够的改进空间,可以为更高级用例而建立。
  • 在第1部分中,我们简要介绍了PHP LINQ端口的PinQ的安装和基本语法。在本文中,我们将看到如何使用PINQ使用MySQL模仿刻面搜索功能。
  • >我们不会涵盖本系列搜索的整个方面。有兴趣的当事方可以参考网站和其他互联网出版物上发表的相关文章。
  • >在网站上类似典型的搜索作品:>

>用户提供了一个关键字或一些关键字要搜索。例如,搜索描述,关键字,类别,标签等中包含“路由器”的产品的“路由器”。>

该网站将返回与标准匹配的产品。

>该站点将提供一些链接来微调搜索。例如,它可能会促使路由器有不同的品牌,并且价格范围可能不同。

>用户可以通过单击提供的不同链接并最终获得更自定义的结果集来进一步筛选结果。
  • 式搜索是如此受欢迎和强大,您几乎可以在每个电子商务网站中体验它。
  • 不幸的是,刻面搜索不是MySQL提供的内置功能。如果我们使用mySQL,我们该怎么办,但也想为我们的用户提供这样的功能?
  • >使用Pinq,我们会看到一种同样强大且直接的方法可以实现这一目标,就像我们在使用其他DB发动机时一样 - 至少在某种程度上。
  • 延长第1部分演示
  • 注意:此部分中的所有代码以及第1部分演示都可以在存储库中找到。
在本文中,我们将扩展第1部分中显示的演示,并添加一些基本的搜索功能。

>让我们从index.php开始,添加以下几行:

>我们刚刚在演示应用程序中创建了另外两个路由(使用Silex)。

>第一个途径是将我们带到页面上,显示与我们第一个搜索行为相匹配的所有记录,即通过提供关键字来搜索。为了使演示简单,我们从示例book_book表中选择所有书籍。它还将显示结果集和面式的链接以进行进一步的导航。

>

>第二个路线将我们带到另一个页面,显示了与上述步骤中产生的结果集中匹配进一步的架构搜索标准的记录。它也将显示刻面搜索链接。

在现实世界实现中,单击一个刻面链接后,将调整结果页面中的任何刻面过滤,以反映结果数据集的统计信息。通过执行此操作,用户可以应用“附加”筛选,首先添加“品牌”,然后再添加“价格范围”等。

>但是,在这个简单的演示中,我们将跳过这种方法,所有刻度搜索和链接只会反映原始数据集的信息。这是我们演示中改进的第一个限制和第一个领域。

从上面的代码中看到,实际函数位于另一个名为pinqdemo.php的文件中。让我们查看提供相关的搜索功能的相关代码。

facet类

首先,我们创建一个代表一个方面的类。通常,一个方面应该具有一些属性:

    它在($ data)
  • 上运行的数据
  • ($ key)
  • >上的密钥IT组
  • 键类型($ type)。它可以是以下之一:

    • >指定一个完整的字符串以进行确切的匹配
    • >指定字符串的部分(通常是开始),以使模式匹配>
    • >按值范围
    • >指定值范围
    如果密钥类型为范围,则需要指定一个值步,以确定范围的上/下限;或者,如果密钥类型是部分字符串,我们需要提供一个数字来指定要使用多少个字母来分组($ range)
  • >
  • 分组是一个方面中最关键的部分。方面可能返回的所有汇总信息取决于“分组”标准。通常,“完整字符串”,“部分字符串”和“值范围”是最常用的。

在此类中,关键功能是根据数据和facet密钥属性返回刻面结果集。我们注意到,对于不同类型的密钥,有不同的方法来分组数据。在上面,我们已经显示了代码在按$范围指定的步骤中按值范围进行分组的代码的样子。

<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()函数中,我们执行以下步骤:
  • >将原始数据转换为可用于进一步处理的可PINQTRAVERAVERABLE对象。>
  • 我们创建3个方面。 “作者”方面将分组在现场作者上,这是一个完整的字符串分组;字段标题和部分字符串分组的“标题”(首发6个字母计数);野外价格和范围分组的“价格”(乘以10步)。
  • >最后,我们获取方面并将其返回到test2函数,以便模板可以渲染数据和方面。
  • 显示刻面和过滤的数据
>

>大多数时候,方面将显示为链接,并将我们带入过滤的数据集。

>我们已经创建了一个路由('demo2/facet/{key}/{value}'),以显示刻面搜索结果和facet链接。

>路由采用两个参数,反映了我们固定的密钥和该密钥的值。最终从该路线调用的test3函数在下面摘录:

>

基本上,根据密钥,我们应用了与传递的值相对应并获取进一步筛选数据的过滤(where子句中的匿名函数)。我们还可以指定刻面数据的顺序。
<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>
登录后复制
登录后复制
登录后复制

>最后,我们在模板中显示数据(以及方面)。此路由呈现与路由“ demo2”使用的模板相同的模板)。

> 接下来,让我们看一下模板,看看如何显示facet链接。我正在使用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>
登录后复制
登录后复制
请注意我们如何构建链接的URI。我们同时使用了外循环的键(k)和内环密钥(vv.key)作为路由('demo2/facet/{key}/{value}')的参数。键(vv.count)的计数用于修饰模板中的显示(作为引导徽章)。

该模板将呈现如下所示:

(第一个显示初始输入页面,第二个显示了一个面积的结果,价格在$ 0到$ 10并由作者订购) 好的,到目前为止,我们已经设法模仿了我们的Web应用程序中的一个面搜索功能!PINQ-查询数据集 - 面式搜索
在我们结束本系列之前,我们将对此演示进行最终研究,看看可以做些改进的演示以及局限性是什么。 PINQ-查询数据集 - 面式搜索

改进要进行

总体而言,这是一个相当基本的演示。我们只是浏览了基本的语法和概念,并将它们伪造成一个可以进行的示例。正如我们之前看到的,可以改进一些区域,以使其更加灵活。

我们需要考虑提供“附加”标准搜索功能。我们当前的实现限制了仅在原始数据上应用于原始数据而不是筛选数据的架子搜索。这是我能想到的最重要的进步。

限制

>此处实施的刻面搜索具有根深蒂固的限制(对于其他方面的搜索实现可能是正确的):

我们每次都从MySQL Server检索数据。

>

此应用使用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呼叫的持续性。这是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语句。我们只通过相同的查询选择查询和3个不同的组,我们只是向Where语句发布一个选择查询,并使用PINQ提供聚合信息。

结论

在这一部分中,我们设法模仿了图书收集站点的刻痕搜索能力。正如我所说,这仅仅是一个可以进行的演示,并且具有足够的改进空间和一些默认限制。让我们知道您是否在此示例上构建并可以向我们展示一些更高级的用例!

> PINQ的作者现在正在研究下一个主要版本版本(版本3)。我确实希望它能变得更强大。

随时在下面留下您的评论和想法!

>

>常见问题(常见问题解答)有关PINQ和FACETED SEARCH

什么是PINQ,与片段搜索有何关系?

PINQ是PHP库,它提供了一种独特,直观且功能强大的查询语言来操纵数组和其他数据集。它旨在简化查询和操纵数据的过程。关于刻面搜索,PINQ可用于创建可以根据多个标准过滤和排序数据的复杂查询,这是FaceTed搜索的核心概念。

PINQ的架构搜索方法与其他方法有何不同?

pinq的FaceTed搜索方法是唯一的,因为它使用了基于PHP的查询语言,该语言是一种广泛使用的编程语言。这使得已经熟悉PHP的开发人员更容易实现式搜索。此外,PINQ的查询语言设计为直观且易于使用,可以简化创建复杂查询的过程。

>可以与其他数据库一起使用PINQ,还是仅限于MySQL? > PINQ不限于MySQL。它可以与任何数据集一起使用,包括数组和其他数据库。这种灵活性使PINQ成为需要使用不同类型数据的开发人员的多功能工具。

> PINQ如何处理大数据集?

PINQ旨在有效地处理大型数据集。它通过使用懒惰的评估策略来做到这一点,这意味着它仅在需要时才能处理数据。在使用大型数据集时,这可以显着提高性能。

>使用PINQ进行片段搜索有什么好处?首先,它简化了创建复杂查询的过程,从而可以节省开发人员的时间和精力。其次,它提供了一种强大而灵活的查询语言,可以处理各种数据类型和结构。最后,它基于PHP,它是一种广泛使用的编程语言,使开发人员更容易学习和使用。

PINQ适合初学者,还是更适合经验丰富的开发人员? 🎜> PINQ设计为直观且易于使用,使其适合初学者和经验丰富的开发人员。但是,使用PINQ。查询语言,可以根据多个标准准确过滤和排序数据。这使其可以提供精确且相关的搜索结果。

可以使用PINQ进行实时搜索吗?

>

是的,PINQ可用于实时搜索。它有效地处理大型数据集及其创建复杂查询的能力使其适合于实时搜索应用程序。

>

PINQ与其他php库相比如何?由于其独特,直观且功能强大的查询语言,从其他PHP库中进行了搜索。它还可以从其可以处理的数据类型方面具有灵活性,并且其对大型数据集的有效处理使其成为开发人员的强大选择。

>

是Pinq开源的,并且可以自定义吗?是的,PINQ是一个开源库,这意味着开发人员可以自定义以适应其特定需求。这种灵活性是使用PINQ进行片段搜索的另一个优点。

>

以上是PINQ-查询数据集 - 面式搜索的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板