六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 1023|回复: 0

使用 PHP 和 Apache Solr 实现企业搜索

[复制链接]
 楼主| 发表于 2014-11-21 17:58:47 | 显示全部楼层 |阅读模式
使用 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 删除一条特定记录,也可以通过查询删除多条记录。

[size=1.166em]回页首
现在使用 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/
该会员没有填写今日想说内容.
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表