Laravel5.5 使用 Elasticsearch 做引擎,scout 全文搜索

背景

最近几个项目要实现全文搜索功能,所以学习了一下elasticsearch的使用和使用过程中遇到的一些坑。自己做一总结,帮助自己复习一下知识,希望能帮助那些也是刚刚开始学习es的同学。大神绕道!
项目框架是:laravel 5.5 
引     擎:elasticsearch
全文搜索包:scout

准备工作

1.下载一个laravel 5.5框架。
2.安装运行es 链接地址,点开链接,根据自己的系统下载安装包,里面关于怎么样安装运行都说的比较清楚。我用的是mac系统。下载后解压。

$ cd elasticsearch-6.4.2 //进入到解压目录
$ ./bin/elasticsearch //本地运行es

开始

1.进入项目目录。

$ cd estest

2.安装Laravel scout 全文搜索包,这里我用的是5.0版本,tamayo/laravel-scout-elastic
用的是4.0版本。这俩个包的版本号是有对应关系的,但是我没有找到对照表,只是安
装的时候实验出来的。

$ composer require laravel/scout=5.0

3.注册服务提供器,你需要将 ScoutServiceProvider 添加到你的配置文件 config/app.php 的 providers 数组中。

'providers' => [
    ...
    Laravel\Scout\ScoutServiceProvider::class,
],

4.生成配置文件。注册好 Scout 的服务提供器之后,你还需使用Artisan 命令
vendor:publish 生成 Scout 的配置文件。这个命令会在你的 config 目录下
生成 scout.php 配置文件。

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

//Laravel 5.5 其实我们不用这么麻烦!直接执行如下命令。这条命令会给你一个list,让你选择publish哪个选项。

$ php artisan vendor:publish

5.因为要使用es做搜索引擎,所以我们要用到一个叫tamayo/laravel-scout-elastic的包。

 $ composer require tamayo/laravel-scout-elastic=4.0

6.添加服务提供器到config/app.php的providers数组中。

// config/app.php
'providers' => [
    ...
    ScoutEngines\Elasticsearch\ElasticsearchProvider::class,
],

7.配置。在config/scout.php文件中添加如下代码。默认使用的是algolia引擎,我们要使用es做引擎。

...
'algolia' => [
    'id' => env('ALGOLIA_APP_ID', ''),
    'secret' => env('ALGOLIA_SECRET', ''),
],
//这里是添加的代码
'elasticsearch' => [
        'index' => env('ELASTICSEARCH_INDEX', 'laravel'),
        'hosts' => [
            env('ELASTICSEARCH_HOST', 'http://127.0.0.1:9200'),
        ],
 ],

8.配置.env文件,添加如下代码。

# scout配置
SCOUT_DRIVER=elasticsearch  //选择搜索引擎
SCOUT_PREFIX=

# elasticsearch 配置
ELASTICSEARCH_INDEX=estest  //设置索引
# elasticsearch服务器地址
ELASTICSEARCH_HOST=http://127.0.0.1:9200  //我用的就是本地的

先别急去实现搜索功能,先来学习几个基本的概念

  • Cluster :集群。可以理解为一个或者多个服务器的集合。用来保存咱们的数据的。群集由唯一名称标识,默认情况下为“elasticsearch”。
  • Node :节点。是集群中单个的服务器。本例子中我的服务器就是本地的127.0.0.1,它就是一个节点。
  • Index:索引。可以理解为msyql中的一个数据库,索引由名称标识(必须全部小写)。
  • Type:类型。可以理解为msyql中的一个表。注意:6.0版本前可以有多个类型。6.0以后的版本已经弃用。一个index下只能有一个type。这个地方当初没有看明白,我项目中好几个model模型都要做全文搜索。所以在每一个model中都定义了一个type。查询自然是不能成功。所以是一个小坑。希望读到的人不要重复这样的错误。也就是说我们把要做全文搜索的字段存进es中一个数据库名字叫index,数据表名字叫type的表中。不管你要查询的字段在哪个model模型中。
  • Document:文档。可以理解为一条数据。

在项目中实现搜索功能

进入项目目录,创建俩个测试model,
$ cd estest  
$ php artisan make:model Models/User
$ php artisan make:model Models/Address

打开Models/User.php,进行设置type,和你要搜索对字段。

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;//这个trait一定要引用的

class User extends Model
{
    use Searchable;
    protected $table = 'user';
    protected $fileable = ['name', 'email', 'phone'];
    // 定义索引里面的类型,上文我们说过,可以把type理解成一个数据表。我们现在要做的就是把我们所有的要全文搜索的字段都存入到es中的一个叫'_doc'的表中。  
    public function searchableAs()  
    {  
        return '_doc';  
    }  
    // 定义有那些字段需要搜索  
    public function toSearchableArray()  
    {  
        return [  
            'user_name' => $this->name,  //user_name加上前缀以区别。因为不同的表里可能会有相同的字段。mysql中的字段是name,email,created_at。在es中我们存储的user_name,user_email,user_created_at。是可以自定义的。
            'user_email' => $this->email,  
            'user_created_at' => $this->created_at,  
        ];  
    }  
}

Address.php中也是这样使用。

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;

class Address extends Model
{
    use Searchable;
    protected $table = 'address';
    protected $fillable = ['home', 'company'];
    public function searchableAs()
    {
        return '_doc';
    }
    public function toSearchableArray()
    {
        return [
            'address_home' => $this->home,
            'address_company' => $this->company,
            'address_created_at' => $this->created_at,
        ];
    }
}

searchableAs(), toSearchableArray(),这俩个方法在Searchable这个trait里,有兴趣的同学可以去看一下源码。现在我们可以去实现搜索功能了,但是我们的es中还没有数据。所以要把我们mysql中数据同步到es中。注意:很多时候我们会用可视化工具操作我们的数据表。这样手动增加的数据是不会自动同步到es中的,所以如果你用搜索查询的数据和你在mysql中的数据不一致的问题,大多都是你的数据没有达到同步。

//把现有的数据同步es中一个索引叫‘estest’,类型叫‘_doc’
php artisan scout:import "App\Models\User"//把User中到数据同步到es中
php artisan scout:import "App\Models\Address" //把Address中数据同步到es中
//如果你已经做过同步了,然后你不小心手动删除或者增加了mysql中到数据,那么你要清空一下es的数据,再从新导入数据。
php artisan scout:flush "App\Models\User"
php artisan scout:flush "App\Models\Address"
php artisan scout:import "App\Models\User"
php artisan scout:import "App\Models\Address"
//如果这样你的数据也还是有问题。那么就要建议你手动删除一下es的索引,然后再从新导入数据。一开始做测试的时候,可以导入数据,成功以后个人不建议再导入数据。我们可以用官网上的保存,删除,更新。。。。让数据自动同步到es上。这样会减少我们数据不同步问题。

Laravel-scout官网链接

搜索例子。

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\User;
use App\Models\Address;

class PostsController extends Controller
{
    public function test(Request $requst)
    {
        $content = $request->content;
        $list = User::search($content)->where('query', ['*user_name*', '*user_email*'])->orderBy('user_created_at.date.keyword', 'desc')->paginate(20)->toArray();
        $res = Address::search($content)->where('query', ['*address_home*', '*address_company*'])->orderBy('address_created_at.date.keyword', 'desc')->paginate(20)->toArray();
    }   
}

现在可以用Model 直接调用search(‘$string’)方法,$string是你要搜索到内容。这样可以实现搜索功能。但是我们的项目需要一般都是要用created_at做排序的,如果我们要用这个字段去做排序,那么就把这个字段也要存入到es中。拿User来举例,我们要做全文搜索到字段是‘user_name’,‘user_email’,但是要用‘user_created_at’排序。这样我们搜一个字符串,没有匹配到user_name,user_email,但是却匹配到user_created_at,这与我们的需求不符。所以我修改了一下源码。但是这里我对源码的理解不是很深,所以没有办法详细的解说怎么回事。我把我改过的源码贴出来。以后理解了我会在写到这里。暂时实现了功能。

修改/vendor/tamayo/laravel-scout-elastic/src/ElasticsearchEngine.php

<?php

namespace ScoutEngines\Elasticsearch;

use Laravel\Scout\Builder;
use Laravel\Scout\Engines\Engine;
use Elasticsearch\Client as Elastic;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Collection as BaseCollection;

class ElasticsearchEngine extends Engine
{
    /**
     * Index where the models will be saved.
     *
     * @var string
     */
    protected $index;

    /**
     * Elastic where the instance of Elastic|\Elasticsearch\Client is stored.
     *
     * @var object
     */
    protected $elastic;

    /**
     * Create a new engine instance.
     *
     * @param  \Elasticsearch\Client  $elastic
     * @return void
     */
    public function __construct(Elastic $elastic, $index)
    {
        $this->elastic = $elastic;
        $this->index = $index;
    }

    /**
     * Update the given model in the index.
     *
     * @param  Collection  $models
     * @return void
     */
    public function update($models)
    {
        $params['body'] = [];

        $models->each(function($model) use (&$params)
        {
            $params['body'][] = [
                'update' => [
                    '_id' => $model->getKey(),
                    '_index' => $this->index,
                    '_type' => $model->searchableAs(),
                ]
            ];
            $params['body'][] = [
                'doc' => $model->toSearchableArray(),
                'doc_as_upsert' => true
            ];
        });

        $this->elastic->bulk($params);
    }

    /**
     * Remove the given model from the index.
     *
     * @param  Collection  $models
     * @return void
     */
    public function delete($models)
    {
        $params['body'] = [];

        $models->each(function($model) use (&$params)
        {
            $params['body'][] = [
                'delete' => [
                    '_id' => $model->getKey(),
                    '_index' => $this->index,
                    '_type' => $model->searchableAs(),
                ]
            ];
        });

        $this->elastic->bulk($params);
    }

    /**
     * Perform the given search on the engine.
     *
     * @param  Builder  $builder
     * @return mixed
     */
    public function search(Builder $builder)
    {
        return $this->performSearch($builder, array_filter([
            'numericFilters' => $this->filters($builder),
            'size' => $builder->limit,
        ]));
    }

    /**
     * Perform the given search on the engine.
     *
     * @param  Builder  $builder
     * @param  int  $perPage
     * @param  int  $page
     * @return mixed
     */
    public function paginate(Builder $builder, $perPage, $page)
    {
        $result = $this->performSearch($builder, [
            'numericFilters' => $this->filters($builder),
            'from' => (($page * $perPage) - $perPage),
            'size' => $perPage,
        ]);

       $result['nbPages'] = $result['hits']['total']/$perPage;

        return $result;
    }

    /**
     * Perform the given search on the engine.
     *
     * @param  Builder  $builder
     * @param  array  $options
     * @return mixed
     */
    protected function performSearch(Builder $builder, array $options = [])
    {
        $params = [
            'index' => $this->index,
            'type' => $builder->index ?: $builder->model->searchableAs(),
            'body' => [
                'query' => [
                    'bool' => [
                        'must' => [['query_string' => [ 'query' => "*{$builder->query}*"]]]
                    ]
                ]
            ]
        ];

        if ($sort = $this->sort($builder)) {
            $params['body']['sort'] = $sort;
        }

        if (isset($options['from'])) {
            $params['body']['from'] = $options['from'];
        }

        if (isset($options['size'])) {
            $params['body']['size'] = $options['size'];
        }
        // if (isset($options['numericFilters']) && count($options['numericFilters'])) {
        //     $params['body']['query']['bool']['must'] = array_merge($params['body']['query']['bool']['must'],
        //         $options['numericFilters']);
        // }
        //这里是修改的地方,组合成我们想要的查询语句
        if(isset($options['numericFilters'][0]['query_string'])) {
            $params['body']['query']['bool']['must'][0]['query_string']['fields'] = $options['numericFilters'][0]['query_string'];
        } else {
            $params['body']['query']['bool']['must'] = array_merge($params['body']['query']['bool']['must'],
                $options['numericFilters']);
        }
        if ($builder->callback) {
            return call_user_func(
                $builder->callback,
                $this->elastic,
                $builder->query,
                $params
            );
        }

        return $this->elastic->search($params);
    }

    /**
     * Get the filter array for the query.
     *
     * @param  Builder  $builder
     * @return array
     */
    protected function filters(Builder $builder)
    {
        return collect($builder->wheres)->map(function ($value, $key) {
            if (is_array($value) && $key != 'query') {
                return ['terms' => [$key => $value]];
            }
            //这里是修改的地方,$key = 'query',$value =['字段1','字段2']。 就是这里的where('query', ['字段1','字段2'])。
            if ($key == 'query') {
                return ['query_string' => $value];
            }
            return ['match_phrase' => [$key => $value]];
        })->values()->all();
    }

    /**
     * Pluck and return the primary keys of the given results.
     *
     * @param  mixed  $results
     * @return \Illuminate\Support\Collection
     */
    public function mapIds($results)
    {
        return collect($results['hits']['hits'])->pluck('_id')->values();
    }

    /**
     * Map the given results to instances of the given model.
     *
     * @param  \Laravel\Scout\Builder  $builder
     * @param  mixed  $results
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @return Collection
     */
    public function map(Builder $builder, $results, $model)
    {
        if ($results['hits']['total'] === 0) {
            return Collection::make();
        }

        $keys = collect($results['hits']['hits'])
                        ->pluck('_id')->values()->all();

        $models = $model->getScoutModelsByIds(
            $builder, $keys
        )->keyBy(function ($model) {
            return $model->getScoutKey();
        });

        return collect($results['hits']['hits'])->map(function ($hit) use ($model, $models) {
            return isset($models[$hit['_id']]) ? $models[$hit['_id']] : null;
        })->filter()->values();
    }

    /**
     * Get the total count from a raw result returned by the engine.
     *
     * @param  mixed  $results
     * @return int
     */
    public function getTotalCount($results)
    {
        return $results['hits']['total'];
    }

    /**
     * Generates the sort if theres any.
     *
     * @param  Builder $builder
     * @return array|null
     */
    protected function sort($builder)
    {
        if (count($builder->orders) == 0) {
            return null;
        }

        return collect($builder->orders)->map(function($order) {
            return [$order['column'] => $order['direction']];
        })->toArray();
    }
}

修改/vendor/laravel/scout/src/Searchable.php

 public function getScoutModelsByIds(Builder $builder, array $ids)
{
    $query = in_array(SoftDeletes::class, class_uses_recursive($this))
                    ? $this->withTrashed() : $this->newQuery();
    //把这行代码注释掉,不然会报错:Undefined property: Laravel\Scout\Builder::$queryCallback
    // if ($builder->queryCallback) {
    //     call_user_func($builder->queryCallback, $query);
    // }

    return $query->whereIn(
        $this->getScoutKeyName(), $ids
    )->get();
}

其实这修改的源码没有那么神秘,它只不过是对es官网的查询接口做的封装,我们只是把能实现需求的查询语句组合替换掉原来的查询语句。所以要想真的明白,还要多看es官网,虽然英文让人痛疼。代码在vendor/tamayo/laravel_scout_elastic/src/ElasticsearchEngine.php里面 。下面就是es给出的查询语句。我们在本地测试可以有2种方式。

1. curl
curl -X POST "localhost:9200/estest/_search" -H 'Content-Type: application/json' -d'
{
    "query": {
        "bool" : {
            "must" : {
                "query_string" : {
                    "fields" : ["user_name", "user_email"],
                    "query" : "*新*"
                }
            }
        }
    }
}'
//结果
{
    "took":12,
    "timed_out":false,
    "_shards":{
        "total":5,
        "successful":5,
        "skipped":0,
        "failed":0
    },
    "hits":{
        "total":1,
        "max_score":1,
        "hits":[
            {
                "_index":"estest",
                "_type":"_doc",
                "_id":"1",
                "_score":1,
                "_source":{
                    "user_name":"新超",
                    "user_email":"1046072048@qq.com",
                    "user_created_at":{
                        "date":"2018-11-15 09:10:40.000000",
                        "timezone_type":3,
                        "timezone":"UTC"
                    },
                    "address_home":"望京酒仙桥",
                    "address_created_at":{
                        "date":"2018-11-15 12:22:53.000000",
                        "timezone":"UTC",
                        "timezone_type":3
                    },
                    "address_company":"顺义石门地铁"
                }
            }
        ]
    }
}
  1. postman

    注意,我们用请求方式是post,Headers里要传值,不然会报错。json数据在body.raw下传。

总结

以前很少写博客,以后会坚持写下去。有什么错误,希望看到的同学帮我指出来。谢谢!
本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由系统于 5年前 自动加精
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 55

折腾了好久,将laravel/scout 5.0.0 版本换成 laravel/scout 5.0.3即可解决Undefined property: Laravel\Scout\Builder::$queryCallback 报错问题。不用手动修改源码。

5.0.3版本的Laravel\Scout\Builder类在5.0.0基础上增加了$queryCallback属性并做了其他修改。

5年前 评论

折腾了好久,将laravel/scout 5.0.0 版本换成 laravel/scout 5.0.3即可解决Undefined property: Laravel\Scout\Builder::$queryCallback 报错问题。不用手动修改源码。

5.0.3版本的Laravel\Scout\Builder类在5.0.0基础上增加了$queryCallback属性并做了其他修改。

5年前 评论

Paginate分页报错问题,是版本问题,部分数据结构改变,导致的Unsupported operand types

1、修改laravel-scout-elastic/src/ElasticsearchEngine.php

file

2、修改laravel/scout/src/Builder.php

file

4年前 评论

@沙漠行者 其实不用改源码的,只是作者可能对 ElasticSearch 的查询语法和排序不是很理解,等理解了 ElasticSearch 就知道该怎么用了。

5年前 评论

@lddtime 原来这样子,谢谢啦 :+1:

5年前 评论

使用php artisan scout:import 模型的数据提示成功import,但是es却没有数据,这个怎么查找原因呢

5年前 评论

@chenweibo 真的抱歉!我一直在忙项目,刚刚看到。但是我想您应该解决了问题!我有时间试一下,希望您可以把解决的方案写下来,共同进步! :stuck_out_tongue_winking_eye:

5年前 评论

@沙漠行者 你们有没有发现php artisan scout:import "\App\Models\Sample"
导入的数据会少 和数据库里面的不一致 少几条

5年前 评论

@chenweibo 有时候会有数据不一致的情况发生,建议先flush,在import。如果还没有解决问题 。最好是清空es中的数据,再从新导入。

5年前 评论

@沙漠行者 是这个包的问题。我在模型里面 设置了模型关联的字段,多对一的关联数据 他只会导入1条。所以会少数据。 我直接用官方的包查了。 导入数据也直接用GO脚本导了。

5年前 评论

{"_index":"lalashop","_type":"_doc","_id":"3","found":false} 数据库中有数据 es(6.5.4)没有写进

图片

5年前 评论

@guyun 我也是 找到解决办法了么

5年前 评论

@guyun 关于数据库和es中数据不一致的问题。
1.使用这个包是怎么同步数据的?是通过使用它的增,删。也就是说不要手动的添加和删除数据库的数据。
2.如果数据怎么导入都不一致,这个问题确实出现过,那么我们就要先彻底的清除es中的数据,在从新import你的model里的数据。这样数据也就可以保持同步了。
3.切忌!如果你手动删除或者添加了数据库中的数据,要先执行scout:flush,再执行 scout:import。
4.如果觉得这个包不好用,可以直接使用原生的语句去写,其实es就相当于一个数据库,可以这么理解。但是其实不一样的。用途不一样。开始对它的语法肯定觉得费劲,多阅读一下官方文档!慢慢就好了!
共勉!共勉! :stuck_out_tongue_winking_eye:

5年前 评论

需要手动新建索引吗?还是 import 的时候会直接按照 env 中的 ELASTICSEARCH_INDEX 值自动创建,还有查看 es 中的数据你是用什么查看的,使用什么可视化工具么?

5年前 评论

@赖皮小鳄鱼
1.索引的创建不需要手动,正如你所说的那样,在env中我们已经设置好了。
2.我不知道有没有可视化工具,因为没有用过所以没有去查询。但是如果是想要看es的数据可以看我文章最后用postman查看数据。或者直接在终端执行原生查询语句接口。官方文档上写的很详细。告诉我们怎么在终端运行了!

5年前 评论

@沙漠行者 我看其他文章中的教程都写到了 esinit 包括创建 mappings ,我按照你的教程完成了,搜索单个字可以,但是搜索词语是都不到的,这个有遇到吗?

5年前 评论

@赖皮小鳄鱼 $list = User::search($content)->where('query', ['user_name', 'user_email'])->orderBy('user_created_at.date.keyword', 'desc')->paginate(20)->toArray(); 这条语句里的‘user_name’的 ‘*’不要省略,还有就是检查一下你改的源码对吗?我改源码就为了解决这个问题。如果你的es版本和我一样,建议你复制我改过的源码!不用分词器,可以查询词语的

5年前 评论

->paginate(20) 报错(如图)
file

改成->get() 可以获取到想要的数据,但是没有分页了,有遇到一样情况的吗?

4年前 评论
zxx 4年前

@songbai 你把你的代码给我看看。我的分页是能用的。

4年前 评论

@沙漠行者
控制器的代码,这个应该没问题

 $handle = \App\Good::search($query)->where('query', ['*goods_name*','*goods_content*']);
            if($request['order'] == 1){
                $handle = $handle->orderBy('goods_stock', 'desc');
            }elseif($request['order'] == 2){
                $handle = $handle->orderBy('goods_price.keyword', 'desc');
            }else{
                $handle = $handle->orderBy('goods_created_at.date.keyword', 'desc');
            }
//            $goods = $handle->get();//正常显示
            $goods = $handle->paginate(10);//报错 Unsupported operand types

$goods = $handle->get();//正常显示的页面,索引内有超过十条数据,用get也只显示出10条

file

我查看了下面的这个代码

  public function paginate(Builder $builder, $perPage, $page)
    {
        $result = $this->performSearch($builder, [
            'numericFilters' => $this->filters($builder),
            'from' => (($page * $perPage) - $perPage),
            'size' => $perPage,
        ]);

        dd($result['hits']['total']);//数组 ??[  "value" => 14 ,"relation" => "eq"]
        dd($perPage);//10
       $result['nbPages'] = $result['hits']['total']/$perPage;

        return $result;
    }

我ES版本用的是7,然后laravel版本是5.6,scout的包之前是 4.0版本,对应的laravel-scout-elastic的包版本是3.0,我有做了升级。刚开始以为是升级的原因,后来本地重新按你的版本重新做了一遍,也是出现同样的错误。

我全新安装了这个sleimanx2/plastic
然后同样也是在使用->get()可以获取数据,使用->paginate(10)分页那边出现
图片
难道是es的问题?

4年前 评论

@songbai 你的代码看着应该没有什么问题,你可以试试 $handle = \App\Good::search($query)->where('query', ['goods_name','goods_content'])->paginate(20); 看看是否报错!如果报错那就是paginate()出错了,如果没有报错应该是你的排序出错了!但是感觉如果是排序出错的话 get()也不会拿到数据!你是在改写这个paginate方法吗?因为我这里没法测试,无法给你具体的解决办法!但是我可以保证我的paginate()可以用的 :joy: :joy: 如果你任务比较急,也确定是分页的问题,可以现在自己手动写个分页!下来在查看到底是怎么回事!

4年前 评论

@songbai 我用自己的数据测试了一下 ,没有问题啊!

file

file

4年前 评论

@沙漠行者 我用了 @Derek 推荐的 sleimanx2/plastic 这个包来做,也是一样的报错,代码:

        $data = Good::search()->match('goods_name','拖拉机')->paginate();//出错
        $data = Good::search()->match('goods_name','拖拉机')->get();//可以读取

->paginate() 出错
file
->get()获取的信息:
file
你的代码应该没有问题,可能是我的es数据问题? 我再仔细排查看下!

4年前 评论

@songbai 单单看这样,我也看不出什么问题 :joy:,不过你可以看下我这个例子,用babenkoivan/scout-elasticsearch-driver来搞的,地址:elasticsearch 实现用户搜索

4年前 评论

@songbai 找到原因告诉我一声 谢谢!

4年前 评论
zxx 4年前
kuner 4年前
十里长亭

@songbai 这个问题其实是elasticsearch版本的问题,太高版本就会报这个错误,换成 elasticsearch 6.2.4并将ik插件也换成 6.2.4就OK

4年前 评论

有大佬遇到 过 scout 已经配置driver为elasticsearch,但是我用脚本跑了一个模型查询之后,用的还是mysql引擎 来查询吗

4年前 评论

@zero风来 用这个包来做的话,只要配置全部对了,是可以实现的。如果你的搜索不是很复杂,很多的话,调es原生API实现也是可以的。

4年前 评论

@沙漠行者 感谢回复,是这样的,我这样写,走的是es查询

file

如果我用 WechatKeyWord::search('登记手机')->first(); 打印出来的结果就是一个集合,日志上也会打印这个sql语句,所以比较懵逼。。。

4年前 评论

@96qbhy 谢谢你,我改过来了!

5年前 评论

@wenqingzzz 已经更新了,但是不知会不会对您有帮助。有问题帮我指正一下哈。谢谢!

5年前 评论
wenqingzzz

我这报错误信息不知道怎么回事
Undefined property: Laravel\Scout\Builder::$queryCallback

5年前 评论

@wenqingzzz 我给出的例子是改动了源码的查询,如果你不想改动源码,你可以安装Laravel-scout官网上给出的方法链式调用。如果你想用我这种查询方式,要改动一下源码,vendor/tamayo/laravel_scout_elastic/src/ElasticsearchEngine.php。如果这不能解决你的问题。你可以把你的问题详细的说一下。我看想能不能帮你解决。

5年前 评论

不错不错,学习了。。。

5年前 评论

能否实现评分的功能,比如 某个字段占得分值比较高

5年前 评论

elasticsearch 使用必须要本地有java的jdk环境吗

5年前 评论

@sensen 服务端要,客户端不用。
我们写 PHP 是客户端调用,使用的是 HTTP Restful API 。可以不用 Java SDK。

5年前 评论

@qufo 我确实对查询语法不是很理解,谢谢你!项目过后,我会在好好学习一下

5年前 评论

也可以尝试一下sleimanx2/plastic这个包来做

5年前 评论
qbhy

配置文件那里写错了,是 config/scout.php 不是 config/app.php

5年前 评论

@zhongjintao 不好意思刚刚看到,不知道具体情况,但是你可以清空一下es的数据,从新导入一下!

5年前 评论
linshuilan

@wenqingzzz 请问最后是怎么解决的呢

5年前 评论

@wenqingzzz /vendor/laravel/scout/src/Searchable.php 有一个getScoutModelsByIds()方法的这段代码注释掉就可以了。
if ($builder->queryCallback) {
call_user_func($builder->queryCallback, $query);
}

5年前 评论
ruke

我最近用了es做了一个订单数据分析, 因为数据快过亿了,所以才用了它, 但我并不是用来搜索的. 我用的是一个很小的包然后改了拿来用的

5年前 评论

@沙漠行者
我也遇到了前人的那个问题。报Undefined property: Laravel\Scout\Builder::$queryCallback错误。
确实,注释掉/vendor/laravel/scout/src/Searchable.php的某段代码就可以正常运行了。
但是有没有其他解决办法呢?这感觉修改源码好像不太妥当。

5年前 评论

能检索数据库存的json格式的数据吗

5年前 评论

大佬们 我有些数组 把json 转成字符串 然后存到数据库这种形式 我怎么检索啊 检索不出来

5年前 评论

json 转字段串存数据库 中文检索不出来 英文好像可以

5年前 评论

@chenweibo
你先看下你 json_encode() 后的汉字是否被编译成 \uXXXX
我不确定是不是这个原因,希望你确认后能再回复我下
如果是的话你可以尝试使用 json_encode($array, 256)json_encode($array, JSON_UNESCAPED_UNICODE)
以字面编码多字节 Unicode 字符
json_encode
预定义常量

5年前 评论

@沙漠行者
关于 laravel/scouttamayo/laravel-scout-elastic 的对照关系,这个不应该是我们操心
laravel/scout 会作为 tamayo/laravel-scout-elastic 的依赖直接被安装
具体请见 laravel-scout-elastic 的 composer.json
file
file

5年前 评论

@lddtime 没有 而且我重新测试了吧数据转成正常的存到表里另外个字段 然后也查不出来,直接不用扩展 直接查也不行, 他存的数据类型不对。 然后我使用了IK插件的 模式查询 没用扩展包。 用ES官方的包 都查的出来。 es版本6.5 也会不会数据类型的问题。他是keyword 用插件创建的txt多少字数都不影响。 用上面的这个包。数字量多的字段我发现查不出来 比如标题就几个字的都没问题

5年前 评论
wenqingzzz

期待更新,正好用这个

5年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!