使用 PHP 和 Apache Solr 实现企业搜索
多值) | 型号年份,例如 2001 | 字符串 | year | 价格 | 单价 | 浮点 | price | 库存 | 是否有存货 | 布尔 | inStock | 功能 | 零部件的功能 | 字符串 | features | 时间标记 | 活动记录 | 字符串 | timestamp | 重量 | 装运重量 | 浮点 | weight |
[size=1.166em]清单 3 显示了汽车零部件索引所使用的 Solr 模式部分。它大部分都是基于默认 Solr 模式。使用的具体字段 —— 名称和属性 —— 只是替换了在默认模式中找到的 fields 元素(如 清单 1 中所示)。 清单 5. 汽车零部件索引模式<?xml version="1.0" encoding="utf-8" ?><schema name="autoparts" version="1.0"> ... <fields> <field name="partno" type="string" indexed="true" stored="true" required="true" /> <field name="name" type="text" indexed="true" stored="true" required="true" /> <field name="model" type="text_ws" indexed="true" stored="true" multiValued="true" required="true" /> <field name="year" type="text_ws" indexed="true" stored="true" multiValued="true" omitNorms="true" /> <field name="price" type="sfloat" indexed="true" stored="true" required="true" /> <field name="inStock" type="boolean" indexed="true" stored="true" default="false" /> <field name="features" type="text" indexed="true" stored="true" multiValued="true" /> <field name="timestamp" type="date" indexed="true" stored="true" default="NOW" multiValued="false" /> <field name="weight" type="sfloat" indexed="true" stored="true" /> </fields> <uniqueKey>partno</uniqueKey> <defaultSearchField>name</defaultSearchField></schema>
[size=1.166em]针对以上字段,需要将汽车零部件数据库导出并格式化以上传到 Solr 中,如清单 6 所示。 清单 6. 为进行索引而格式化的汽车零部件数据库<add><doc> <field name="partno">1</field> <field name="name">Spark plug</field> <field name="model">Boxster</field> <field name="model">924</field> <field name="year">1999</field> <field name="year">2000</field> <field name="price">25.00</field> <field name="inStock">true</field></doc><doc> <field name="partno">2</field> <field name="name">Windshield</field> <field name="model">911</field> <field name="year">1991</field> <field name="year">1999</field> <field name="price">15.00</field> <field name="inStock">false</field></doc></add>
[size=1.166em]让我们安装新索引模式并把数据装入 Solr。首先,通过使用 Ctrl+C 组合键来停止 Solr 守护进程(如果它仍在运行)。在 example/solr/conf/schema.xml 中制作现有 Solr 模式的归档。接下来,通过清单 6 创建一个文本文件,将其保存到 /tmp/schema.xml 中,然后复制到 example/solr/conf/schema.xml 中。为清单 7 中所示的数据创建另一个文件。现在,您可以重新启动 Solr 并使用示例所提供的 posting 实用程序。 清单 7. 启用带有新模式的 Solr$ cd apache-solr-1.2/example$ cp solr/conf/schema.xml solr/conf/default_schema.xml$ chmod a-w solr/conf/default_schema.xml$ vi /tmp/schema.xml...$ cp /tmp/schema.xml solr/conf/schema.xml$ vi /tmp/parts.xml...$ java -jar start.jar ...2007-11-11 16:56:48.279::INFO: Started SocketConnector @ 0.0.0.0:8983$ java -jar exampledocs/post.jar /tmp/parts.xmlSimplePostTool: version 1.2SimplePostTool: WARNING: Make sure your XML documents are encoded in UTF-8, other encodings are not currently supportedSimplePostTool: POSTing files to http://localhost:8983/solr/update...SimplePostTool: POSTing file parts.xmlSimplePostTool: COMMITting Solr index changes...
[size=1.166em]成功!如果需要检验索引是否存在并包含两个文档,请将浏览器再次指向 http://localhost:8983/solr/admin/。您应当会在页面顶部看到 “(autoparts)”。如果看到了,请单击页面中间的查询框并键入 partno: 1 or partno: 2。 [size=1.166em]结果应当类似下面的内容: 3 on 10 0 partno: 1 OR partno: 2 2.2true Boxster 924 Spark plug 1 25.0 2007-11-11T21:58:45.899Z 1999 2000 false 911 Windshield 2 15.0 2007-11-11T21:58:45.953Z 1991 1999
[size=1.166em]尝试其他一些查询。Lucene 维基中介绍了 Lucene 查询(Solr 中的搜索引擎)的语法(请参阅 参考资料)。 [size=1.166em]您还应当尝试再次编辑和载入数据。由于声明了 partno 字段惟一,因此重复上传同一个部件号将只用新记录替换旧索引记录。除了 add 命令之外,您还可以使用 commit、optimize 和 delete。最后一个命令可以按照 ID 删除一条特定记录,也可以通过查询删除多条记录。
现在使用 PHP[size=1.166em]最后,PHP 将参与到这个示例中。 [size=1.166em]至少有两个 PHP Solr API。最健壮的实现是 Donovan Jimenez 的 PHP Solr Client(请参阅 参考资料)。代码是在与 Solr 相同的条款下许可开发的,它有扩展文档,并且与 Solr V1.2 兼容。撰写本文时的最新版本是在 2007 年 10 月 2 日发布的。 [size=1.166em]Solr Client 将提供四个 PHP 类: - Apache_Solr_Service 表示 Solr 服务器。使用这些方法来 ping 服务器,添加和删除文档,提交更改,优化索引,以及运行查询。
- Apache_Solr_Document 收录 Solr 文档。该类的方法将管理(关键字,值)对和多值字段。字段值可以通过直接解除引用来访问,例如$document->title = 'Something'; ... echo $document->title;。
- Apache_Solr_Response 封装 Solr 响应。这段代码依赖于 json_decode() 函数,该函数是 PHP V5.2.0 和更高版本附带的,也可以用 PHP Extension Community Library(PECL —— 请参阅 参考资料)来安装。
- Apache_Solr_Service_Balancer 将增强 Apache_Solr_Service,允许您连接到一个分发中的多项 Solr 服务。本文中没有介绍该类。
[size=1.166em]下载 PHP Solr Client(请参阅 参考资料)并将其解压缩到工作目录中。切换到 SolrPhpClient。接下来,查看文件 Apache/Solr/Service.php。撰写本文时,第 335 行缺少了拖尾分号。编辑该文件并添加分号(如果有必要)。另请查看文件 Apache/Solr/Document.php。在第 112 行至第 117 行中应当读出如下内容。 if (!is_array($this->_fields[$key])){ $this->_fields[$key] = array($this->_fields[$key]);}$this->_fields[$key][] = $value;
[size=1.166em]更正文件后,可以在其他 PHP 库旁边安装 Apache 目录。 [size=1.166em]下列代码显示了连接 Solr 服务、向索引中添加两个文档和运行先前使用的零部件号查询的 PHP 应用程序。 清单 8. 用于连接、载入和查询 Solr 索引的样例 PHP 应用程序<?php require_once( 'Apache/Solr/Service.php' ); // // // Try to connect to the named server, port, and url // $solr = new Apache_Solr_Service( 'localhost', '8983', '/solr' ); if ( ! $solr->ping() ) { echo 'Solr service not responding.'; exit; } // // // Create two documents to represent two auto parts. // In practice, documents would likely be assembled from a // database query. // $parts = array( 'spark_plug' => array( 'partno' => 1, 'name' => 'Spark plug', 'model' => array( 'Boxster', '924' ), 'year' => array( 1999, 2000 ), 'price' => 25.00, 'inStock' => true, ), 'windshield' => array( 'partno' => 2, 'name' => 'Windshield', 'model' => '911', 'year' => array( 1999, 2000 ), 'price' => 15.00, 'inStock' => false, ) ); $documents = array(); foreach ( $parts as $item => $fields ) { $part = new Apache_Solr_Document(); foreach ( $fields as $key => $value ) { if ( is_array( $value ) ) { foreach ( $value as $datum ) { $part->setMultiValue( $key, $datum ); } } else { $part->$key = $value; } } $documents[] = $part; } // // // Load the documents into the index // try { $solr->addDocuments( $documents ); $solr->commit(); $solr->optimize(); } catch ( Exception $e ) { echo $e->getMessage(); } // // // Run some queries. Provide the raw path, a starting offset // for result documents, and the maximum number of result // documents to return. You can also use a fourth parameter // to control how results are sorted and highlighted, // among other options. // $offset = 0; $limit = 10; $queries = array( 'partno: 1 OR partno: 2', 'model: Boxster', 'name: plug' ); foreach ( $queries as $query ) { $response = $solr->search( $query, $offset, $limit ); if ( $response->getHttpStatus() == 200 ) { // print_r( $response->getRawResponse() ); if ( $response->response->numFound > 0 ) { echo "$query <br />"; foreach ( $response->response->docs as $doc ) { echo "$doc->partno $doc->name <br />"; } echo '<br />'; } } else { echo $response->getHttpStatusMessage(); } }?>
[size=1.166em]首先,代码将连接到给定端口和路径上名为 Solr 的服务器,并将使用 ping() 方法来检验服务器是否可运行。 [size=1.166em]接下来,代码将把表示为 PHP 数组的记录转换为 Solr 文档。如果字段有单个值,则简单的访问程序将把(关键字,值)对添加到文档中。如果字段有多个值,则用特殊函数 setMultiValue() 把值列表赋给关键字。您可以看到此过程非常类似于 Solr 文档的 XML 表示。 [size=1.166em]作为一项优化,addDocuments() 将把多个文档插入索引。后续的 commit() 和 optimize() 函数将完成添加操作。 [size=1.166em]在底部,多个查询将从索引中检索数据。您可以通过两个函数查看结果:getRawResponse() 函数将生成完整的未解析结果,而 docs() 函数将返回带有指定访问程序的文档数组。 [size=1.166em]如果查询未能从 Solr 获得确认,代码将输出错误消息。空结果集将不产生输出。
结束语[size=1.166em]Solr 令人难以置信地强大,并且使用 PHP API 可以迅速地与任何平台集成。但更棒的是,Solr 易于安装和运行,并且可以根据需要启用高级功能。最棒的是,Solr 是免费的。不用购买搜索引擎。省下您的钱,使用 Solr 吧。 [size=1.166em]访问 Solr Web 站点了解包括排序、分类结果和复制在内的高级配置的更多信息。Lucene Web 站点是另一个信息源,因为它是 Solr 系统下的搜索技术。 使用 PHP 和 Apache Solr 实现企业搜索
摘自:http://www.ibm.com/developerwork ... /os-php-apachesolr/
|