tomwalder/php-appengine-search

Google App Engine 搜索库 for PHP

v0.0.4-alpha 2017-03-23 08:17 UTC

This package is auto-updated.

Last update: 2024-09-06 11:45:53 UTC


README

Build Status Coverage Status

在 Google App Engine 上为 PHP 实现全文搜索

这个库提供了原生 PHP 访问 Google App Engine 搜索 API 的方式。

在撰写本文时,没有现成的从 PHP 运行时访问 Google App Engine 全文搜索 API 的方法。

通常这意味着开发人员无法使用 Python/Java/Go 代理模块 来访问该服务 - 这增加了复杂性、另一种语言、额外的潜在故障点以及性能影响。

ALPHA 该库处于非常早期的开发阶段。请勿在生产环境中使用。它会发生变化。

目录

示例

我发现示例是决定是否尝试库的好方法,所以这里有一些供您参考。

// Schema describing a book
$obj_schema = (new \Search\Schema())
    ->addText('title')
    ->addText('author')
    ->addAtom('isbn')
    ->addNumber('price');
        
// Create and populate a document
$obj_book = $obj_schema->createDocument([
    'title' => 'The Merchant of Venice',
    'author' => 'William Shakespeare',
    'isbn' => '1840224312',
    'price' => 11.99
]);
    
// Write it to the Index
$obj_index = new \Search\Index('library');
$obj_index->put($obj_book);

在这个例子中,我使用了创建文档时的替代数组语法 - 但您也可以这样做

$obj_book = $obj_schema->createDocument();
$obj_book->title = 'Romeo and Juliet';
$obj_book->author = 'William Shakespeare';
$obj_book->isbn = '1840224339';
$obj_book->price = 9.99;

现在我们来做一个简单的搜索并显示输出

$obj_index = new \Search\Index('library');
$obj_response = $obj_index->search('romeo');
foreach($obj_response->results as $obj_result) {
    echo "Title: {$obj_result->doc->title}, ISBN: {$obj_result->doc->isbn} <br />", PHP_EOL;
}

演示应用程序

搜索酒吧!

应用程序: http://pub-search.appspot.com/

代码: https://github.com/tomwalder/pub-search

入门

使用 Composer 安装

要使用 Composer 安装,请在您的 composer.json 中使用此 require 行以获取最新功能,dev-master

"tomwalder/php-appengine-search": "v0.0.4-alpha"

或者,如果您正在使用命令行

composer require tomwalder/php-appengine-search

您可能需要 minimum-stability: dev

查询

您可以为 Index::search 提供一个简单的查询字符串

$obj_index->search('romeo');

对于更多控制和选项,您可以提供一个 Query 对象

$obj_query = (new \Search\Query($str_query))
   ->fields(['isbn', 'price'])
   ->limit(10)
   ->sort('price');
$obj_response = $obj_index->search($obj_query);

查询字符串

一些简单的、有效的查询字符串

  • price:2.99
  • romeo
  • dob:2015-01-01
  • dob < 2000-01-01
  • tom AND age:36

有关更多信息,请参阅 Python 参考文档: https://cloud.google.com/appengine/docs/python/search/query_strings

排序

$obj_query->sort('price');
$obj_query->sort('price', Query::ASC);

限制和偏移量

$obj_query->limit(10);
$obj_query->offset(5);

返回字段

$obj_query->fields(['isbn', 'price']);

表达式

该库支持在结果中请求任意表达式。

$obj_query->expression('euros', 'gbp * 1.45']);

这些可以通过结果文档上的 Document::getExpression() 方法访问,如下所示

$obj_doc->getExpression('euros');

通过 ID 获取文档

您可以直接从索引中通过其唯一的 Doc ID 获取单个文档

$obj_index->get('some-document-id-here');

评分

您可以通过调用 Query::score 方法来启用 MatchScorer。

如果您这样做,结果集中的每个文档都将根据搜索词频率由搜索 API 进行评分 - Google。

如果没有它,所有文档的评分将为 0。

$obj_query->score();

并且结果...

foreach($obj_response->results as $obj_result) {
    echo $obj_result->score, '<br />'; // Score will be a float
}

多排序和评分

如果您应用了 score()sort(),可能会浪费循环次数并花费金钱。只有当您打算按分数排序时,才对文档进行评分。

如果您需要混合按分数和其他字段的排序,可以使用魔法字段名 _score,如下所示 - 在这里,我们首先按价格排序,然后按分数排序,因此价格相同的记录将按其分数排序。

$obj_query->score()->sort('price')->sort('_score');

辅助查询和工具

距离

一个常见的用例是根据从已知Geopoint的距离搜索具有Geopoint字段的文档,例如:“查找附近的酒吧”。

有一个辅助方法可以为您完成这项工作,并且它还会在响应中返回距离(以米为单位)。

$obj_query->sortByDistance('location', [53.4653381,-2.2483717]);

这将返回结果,最近的首先显示,并且将返回一个表示距离的表达式 - 前缀为 distance_from_

$obj_result->doc->getExpression('distance_from_location');

自动完成

自动完成是搜索解决方案中最受欢迎和最有用的功能之一。

这可以通过Google App Engine搜索API相对容易地实现,只需稍加技巧!

搜索API不支持本地支持“边缘n-gram”分词(这是我们自动完成所需的!)。

因此,您可以使用库来完成此操作 - 当创建文档时,设置一个带有从包含的 Tokenizer::edgeNGram 函数输出的第二个文本字段。

$obj_tkzr = new \Search\Tokenizer();
$obj_schema->createDocument([
    'name' => $str_name,
    'name_ngram' => $obj_tkzr->edgeNGram($str_name),
]);

然后您可以像这样轻松运行自动完成查询

$obj_response = $obj_index->search((new \Search\Query('name_ngram:' . $str_query)));

您可以在我的“酒吧搜索”演示应用程序中看到使用此功能的完整演示应用程序。

创建文档

模式与字段类型

根据Python文档,可用的字段类型如下

  • 原子 - 不可分割的字符字符串
  • 文本 - 可以按单词进行搜索的纯文本字符串
  • HTML - 包含HTML标记标签的字符串,只有标记标签外的文本可以搜索
  • 数字 - 浮点数
  • 日期 - 包含年/月/日和可选时间的日期
  • Geopoint - 纬度和经度坐标

日期

我们支持 DateTime 对象或格式为 YYYY-MM-DD(PHP date('Y-m-d'))的日期字符串。

$obj_person_schema = (new \Search\Schema())
    ->addText('name')
    ->addDate('dob');

$obj_person = $obj_person_schema->createDocument([
    'name' => 'Marty McFly',
    'dob' => new DateTime()
]);

Geopoint - 位置数据

创建一个包含Geopoint字段的条目

$obj_pub_schema = (new \Search\Schema())
    ->addText('name')
    ->addGeopoint('where')
    ->addNumber('rating');

$obj_pub = $obj_pub_schema->createDocument([
    'name' => 'Kim by the Sea',
    'where' => [53.4653381, -2.2483717],
    'rating' => 3
]);

批量插入

如果您有多个文档,批量插入效率更高。一次最多可以插入200个文档。

只需将Document对象的数组传递给 Index::put() 方法即可,如下所示

$obj_index = new \Search\Index('library');
$obj_index->put([$obj_book1, $obj_book2, $obj_book3]);

替代数组语法

除了直接构造一个新的 Search\Document 并设置其成员数据外,还可以使用 Search\Schema::createDocument 工厂方法,如下所示。

$obj_book = $obj_schema->createDocument([
    'title' => 'The Merchant of Venice',
    'author' => 'William Shakespeare',
    'isbn' => '1840224312',
    'price' => 11.99
]);

命名空间

在构建索引时,您可以设置一个命名空间。这将允许您支持多租户应用程序。

$obj_index = new \Search\Index('library', 'client1');

分类

搜索API支持两种类型的文档分面用于分类,ATOM和NUMBER。

ATOM可能是您最熟悉的一种,结果集将包括每个唯一分面的计数,类似于以下内容

对于衬衫尺寸

  • 小号(9)
  • 中号(37)

将分面添加到文档中

$obj_doc->atomFacet('size', 'small');
$obj_doc->atomFacet('colour', 'blue');

在结果中获取分面

$obj_query->facets();

删除文档

您可以通过调用 Index::delete() 方法来删除文档。

它支持一个或多个 Document 对象 - 或一个或多个Document ID字符串 - 或对象和ID字符串的混合!

$obj_index = new \Search\Index('library');
$obj_index->delete('some-document-id');
$obj_index->delete([$obj_doc1, $obj_doc2]);
$obj_index->delete([$obj_doc3, 'another-document-id']);

本地开发环境

由于它包含用于支持Python、Java和Go App Engine运行时的功能,因此搜索API支持本地。

最佳实践、免费配额、成本

与大多数App Engine服务一样,搜索是免费的... 但有一个限制!

以及一些值得阅读的最佳实践

Google 软件

我必须包含来自Google的2个文件来使此功能正常工作 - 这是搜索API的协议缓冲区实现。您可以在 /libs 文件夹中找到它们。

它们也可以直接从以下仓库获取:https://github.com/GoogleCloudPlatform/appengine-php-sdk

这两个文件版权属于2007年谷歌公司。

一旦它们被纳入实际的PHP运行时中,我将从这里移除它们。

感谢@sjlangley的帮助。

其他App Engine软件

如果您喜欢这个,您可能对我的PHP Google Cloud Datastore库,PHP-GDS感兴趣