laravel scout_使用Laravel Scout和Algolia实现地理搜索

laravel scout

Laravel Scout makes it very easy to setup an external search engine to create consumer-grade search quickly. The package comes with Algolia as a default search engine. I'd like to demonstrate how to make use of the geo-location search feature with Scout.

Laravel Scout使设置外部搜索引擎非常容易,以快速创建消费者级搜索。 该软件包随附Algolia作为默认搜索引擎。 我想演示如何在Scout中利用地理位置搜索功能。

In this tutorial, you'll learn how to prepare your data for Algolia and Laravel Scout to retrieve items based on location.

在本教程中,您将学习如何为Algolia和Laravel Scout准备数据以根据位置检索项目。

We recommend you use front-end search for your app because this implementation model is most efficient. That being said, there are cases where you need backend search, for instance, if you want to generate reports.

我们建议您对应用程序使用前端搜索 ,因为这种实施模型效率最高。 话虽如此,在某些情况下,例如,如果您想生成报告,则需要进行后端搜索。

入门 ( Getting Started )

For this tutorial, I quickly set up a Laravel app with dummy data of airports around the world. You can find the project on GitHub. You can install it by following the notes in the readme.

对于本教程,我快速设置了一个Laravel应用程序,其中包含世界各地机场的虚拟数据。 您可以在GitHub上找到该项目 。 您可以按照自述文件中的说明进行安装。

If your use case is different or your data isn’t organised this way, feel free to post to our community forum.

如果您的用例不同或您的数据不是按照这种方式组织的,请随时发布到我们的社区论坛

步骤1:安装侦察员 ( Step 1: Install Scout )

Scout comes as a separate package, we'll use composer to pull it into our project.

Scout作为一个单独的软件包提供,我们将使用composer将其拉入我们的项目。

The whole point of Scout is to add an abstraction layer so your code will be the same for any search engine you choose. Since we're using Algolia, this will require our PHP client.

Scout的重点是添加一个抽象层,因此您选择的任何搜索引擎的代码都将相同。 由于我们使用的是Algolia,因此这需要我们PHP客户端。

composer require laravel/scout
composer require algolia/algoliasearch-client-php

Once the PHP client is installed, let’s configure our configuration and specify Algolia as a search provider.. Simply open up the config/app.php file and add Scout in the providers array.

安装PHP客户端后,让我们配置我们的配置并将Algolia指定为搜索提供程序。只需打开config / app.php文件,然后在providers数组中添加Scout。

Laravel\Scout\ScoutServiceProvider::class,

Lastly, publish the package configuration. You don't have to edit the file, everything can be set in your .env configuration file.

最后,发布软件包配置。 您无需编辑文件,所有内容都可以在.env配置文件中进行设置。

php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"

Now, open up your .env file and add your Algolia credentials. You can find these details in your Algolia dashboard, under the API keys tab.

现在,打开您的.env文件并添加您的Algolia凭据。 您可以在Algolia仪表板的“ API密钥”标签下找到这些详细信息。

ALGOLIA_APP_ID=QWERTY12AB
ALGOLIA_SECRET=YOUR_ADMIN_API_KEY

步骤2:格式化资料以建立索引 ( Step 2: Format your data for indexing )

Algolia’s storage is schema-less, meaning all your data will be represented as a JSON object.

Algolia的存储空间较少,这意味着您的所有数据都将表示为JSON对象。

Algolia requires a special attributes to store the coordinates. It has to be set as follows:

Algolia需要特殊的属性来存储坐标。 必须将其设置如下:

{
    other: 'attributes', 
    _geoloc: {
        lat: 0,
        lng: 0
    }
}

Laravel Scout transforms your model into an array before sending data to Algolia, using the method [toSearchableArray()](https://laravel.com/docs/5.4/scout#configuring-searchable-data). So we'll simply override this method to set the _geoloc attribute.

Laravel Scout使用[toSearchableArray()](https://laravel.com/docs/5.4/scout#configuring-searchable-data)方法将模型发送到Algolia之前,将您的模型转换为数组。 因此,我们将简单地重写此方法来设置_geoloc属性。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;

class Airport extends Model
{
    use Searchable;

    public function toSearchableArray()
    {
        $record = $this->toArray();

        $record['_geoloc'] = [
            'lat' => $record['latitude'],
            'lng' => $record['longitude'],
        ];

        unset($record['created_at'], $record['updated_at']); // Remove unrelevant data
        unset($record['latitude'], $record['longitude']);

        return $record;
    }
}

Once it's imported, you will see your data in your Algolia Dashboard.

导入后,您将在Algolia仪表板中看到您的数据。

Your imported data in Algolia dashboard

专业提示 (ProTips)

It’s possible to index multiple locations for one model, it doesn't make sense for an airport but you could have:

可以为一个模型建立多个位置索引,这对于机场来说没有意义,但是您可以:

$record['_geoloc'] = [
    ['lat' => $record['lat1'], 'lng' => $record['lng1']],
    ['lat' => $record['lat2'], 'lng' => $record['lng2']],
    ['lat' => $record['lat3'], 'lng' => $record['lng3']],
];

步骤3:搜寻您的记录 ( Step 3: Search for your records )

Because we use the Searchable trait, we can use the search() static method to look for our data.

因为我们使用Searchable特征,所以我们可以使用search()静态方法来查找数据。

Airport::search('CDG');

Here’s what happens when this code is executed:

执行此代码后,将发生以下情况:

  1. Laravel calls Algolia to get relevant results

    Laravel致电Algolia获得相关结果
  2. It creates a collection based on the IDs of the records retrieved

    它基于检索到的记录的ID创建一个集合
  3. And finally pull data from the app database to instantiate proper models

    最后从应用数据库中提取数据以实例化适当的模型

The good news is that search() takes a callback as a second arguments to alter the request made to Algolia. We'll hook just before step 1 to search by locations.

好消息是search()将回调作为第二个参数来更改对Algolia的请求。 我们将在执行第1步之前挂接以按位置进行搜索。

在位置周围搜索(反向地理编码) (Searching around a location (reverse geocoding))

You need two pieces of information to search per location: the coordinates and a radius. This is what we'll pass to Algolia using the callback.

每个位置需要两点信息:坐标和半径。 这就是我们将使用回调传递给Algolia的内容。

Let's say we want the airports around Paris. In this example, we'll not search in the text, but only per location. Hence, we'll leave the query empty.

假设我们要巴黎附近的机场。 在此示例中,我们将不搜索文本,而仅按位置搜索。 因此,我们将查询保留为空。

By default, Algolia returns the results sorted by ascending distance: the closest comes first.

默认情况下,Algolia返回按递增距离排序的结果:最接近的优先。

$lat = 48.8588377;
$lng = 2.2775175;
$radius = 150000; // Value has to be in meters

Airport::search('', function ($algolia, $query, $options) use ($lat, $lng, $radius) {
    $location =  [
        'aroundLatLng' => $lat.','.$lng,
        'aroundRadius' => $radius,
    ];

    $options = array_merge($options, $location);

    return $algolia->search($query, $options);
});

The radius is, in fact, optional. If you don't provide radius, Algolia will return the closest 1,000 results.

实际上,半径是可选的。 如果不提供半径,则Algolia将返回最接近的1,000个结果。

If you want to know more about how to set the options to search by location, you can refer to the official documentation.

如果您想进一步了解如何设置按位置搜索的选项,可以参考官方文档

在区域内搜索 (Searching inside a zone)

Algolia can also search inside a zone. A zone, called a bounding box here, is defined by a set of at least 2 coordinates. In this case the rectangle where the line between those 2 points is the diagonal.

阿尔及利亚还可以在区域内搜索。 一个区域(在此称为边界框)由一组至少2个坐标定义。 在这种情况下,这两个点之间的线是对角线的矩形。

For this example we'll look for an airport in the UK. I formed a polygon using Google Maps. I could have used France for this example, but the borders were too complicated. Now that I think about it, I probably should have chosen the state of Colorado.

在此示例中,我们将寻找英国的机场。 我使用Google地图形成了一个多边形。 我可以以法国为例,但是边界太复杂了。 现在,考虑一下,我可能应该选择科罗拉多州。

Airport::search($query, function ($algolia, $query, $options) {
    $polygonAroundTheUK = [
        52.9332312, -1.9937525, // Point 1 lat, lng
        52.1312677, -2.0434894, // Point 2 lat, lng
        52.7029492,-1.2530685, // Point 3 lat, lng
        51.5262792, 0.1192389, // Point 4 lat, lng
        48.8364598, 1.7006836, // Point 5 lat, lng
    ];

    $location = [
        'insidePolygon' => [$polygonAroundTheUK]
    ];

    $options = array_merge($options, $location);

    return $algolia->search($query, $options);
})

利用宏 ( Leveraging Macros )

Laravel Scout 3.0.5 added the Macroable capability to the builder. This is a great way to add new method to a class without overriding it. A good place to add your custom macros would be in the boot method of your AppServiceProvider.

Laravel Scout 3.0.5向构建器添加了Macroable功能 。 这是将新方法添加到类而不覆盖它的好方法。 添加自定义宏的一个好地方是在AppServiceProviderboot方法中。

if (! Builder::hasMacro('aroundLatLng')) {
    Builder::macro('aroundLatLng', function ($lat, $lng) {
        $callback = $this->callback;

        $this->callback = function ($algolia, $query, $options) use ($lat, $lng, $callback) {
            $options['aroundLatLng'] = (float) $lat . ',' . (float) $lng;

            if ($callback) {
                return call_user_func(
                    $callback,
                    $algolia,
                    $query,
                    $options
                );
            }

            return $algolia->search($query, $options);
        };

        return $this;
    });
}

This macro will hide all the burden of the callback behind a nice function, then you get:

该宏会将回调的所有负担隐藏在一个不错的函数后面,然后您将得到:

// Return closest 1,000 airport from paris, ordered by distance
Airport::search('')->aroundLatLng(48.8588377, 2.2775175);

I created a little project to gather useful algolia-specific macro. Feel free to contribute!

我创建了一个小项目来收集有用的特定于算法的宏 。 随时贡献!

结论 ( Conclusion )

This tutorial is only a small example of what you can do with Scout and Algolia. If you have any suggestions or if you want to share your use case, feel free to leave a comment or join our community. I'll be happy to answer.

本教程只是您可以使用Scout和Algolia进行操作的一个小示例。 如果您有任何建议或想要分享您的用例,请随时发表评论或加入我们的社区 。 我很乐意回答。

翻译自: https://scotch.io/tutorials/achieving-geo-search-with-laravel-scout-and-algolia

laravel scout

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值