Yii2 elasticSearch 多值查询 和 查询数组字段
代码如下:$data 是一个数组。
if(is_array($data) && !empty($data )){ $elasticsearch = Yii::$app->elasticsearch; $bulkclient = $elasticsearch->createBulkCommand(); # elasticSearch的index,相当于mysql的数据库 $index_name = 'fecshop'; # elasticSearch的type,相当于mysql的table $type_name = 'whole_free_sku_data'; echo $index_name."###".$type_name." \n"; foreach($data as $one){ $i++; $a = []; $a['sku_id'] = $one['_id']; $value = $one['value']; # 将多维数组部分进行序列化。 if(is_array($value) && !empty($value )){ foreach($value as $k => $v){ if(in_array($k,['devide','country_code','browser_name','operate'])){ if(is_array($v) && !empty($v)){ $vv = []; foreach($v as $vk => $o){ $vv[] = serialize([$vk=>$o]); } $v = $vv; } } $a[$k] = $v; } } # 去掉_id字段。 unset($a['_id']); $bulkclient->addAction(array( 'index' => array( '_index'=> $index_name, '_type' => $type_name, '_id' => $one['_id'], ) ), $a); } $bulkclient->execute(); }
elasticsearch的查询:查询器query 和 过滤器filter
关于查询器query和过滤器filter的区别,可以参看文章:http://www.tuicool.com/articles/7rqAFne
public function getTableTbody() { $pageNum = 3; $numPerPage = 50; $offset = ($pageNum - 1) * $numPerPage; $limit = $numPerPage ; $sort = ['emails' => ['order' => 'desc']]; # emails 按照desc的方式进行排序 $query = $this->_getSearchQuery(); $result = $query->orderby($sort)->offset($offset)->limit($limit)->asArray()->all(); $data = \yii\helpers\BaseArrayHelper::getColumn($result, '_source'); if(!empty($data)) { foreach($data as $dk => $dr) { // do something } } }
上面使用的_getSearchQuery() 方法如下:
public function _getSearchQuery(){ # $field_1 $field_2 都是字段 $filter_arr = [ 'bool' => [ 'must' => [ ['term' => [$field_1 => 'xxxxxxx']] # $emails_arr 是数组。 ['terms' => [$field_2 => $emails_arr]] # 在查询的字段只有一个值的时候,应该使用term而不是terms,在查询字段包含多个的时候才使用terms ] ], ]; # $field_1 $field_2 都是字段 $query_arr = [ 'bool' => [ 'must' => [ ['match' => [$field_1 => 'xxxxx']], ], 'should' => [ # 关于wildcard查询可以参看文章:http://blog.csdn.net/dm_vincent/article/details/42024799 ['wildcard' => [$field_2 => "W?F*HW"]] ] ], ]; # Customer 就是elasticSearch 的 model $query = Customer::find()->filter($filter_arr)->query($query_arr); return $query; }
对于上面出现的must should,自己查资料,了解elasticSearch
对于term 相当于等于
对于terms相当于mysql中的in
在上述查询中,filter是不分词,不进行同义词查询的,速度肯定要快
query会进行同义词查询的,速度肯定要慢一些的。
在上一篇文章,我们配置好了es,那么,我们开始配置model
<?php namespace appadmin\code\Ta\models\elasticSearch; use yii\elasticsearch\ActiveRecord; class Customer extends ActiveRecord { public static $currentIndex; # 定义db链接 public static function getDb() { return \Yii::$app->get('elasticsearch'); } # db public static function index() { return 'ta'; } # table public static function type() { return 'customer'; } # 属性 public function attributes() { $mapConfig = self::mapConfig(); return array_keys($mapConfig['properties']); } # mapping配置 public static function mapConfig(){ return [ 'properties' => [ 'customer_id' => ['type' => 'long', "index" => "not_analyzed"], 'uuids' => ['type' => 'string', "index" => "not_analyzed"], 'updated_at' => ['type' => 'long', "index" => "not_analyzed"], 'emails' => ['type' => 'string',"index" => "not_analyzed"], ] ]; } public static function mapping() { return [ static::type() => self::mapConfig(), ]; } /** * Set (update) mappings for this model */ public static function updateMapping(){ $db = self::getDb(); $command = $db->createCommand(); if(!$command->indexExists(self::index())){ $command->createIndex(self::index()); } $command->setMapping(self::index(), self::type(), self::mapping()); } public static function getMapping(){ $db = self::getDb(); $command = $db->createCommand(); return $command->getMapping(); } }
index()方法,可以看成mysql的db
type()可以看成mysql的table,但是实质是有差别的。
mapConfig()是配置mapping,关于elasticSearch的mapping,您可以参看下面的一些资料:
https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html
http://blog.csdn.net/lvhong84/article/details/23936697
等等,您可以去搜搜。
由于我不想让elasticSearch 进行分词等操作,我只是想当成一个和数据库类似的搜索,因此,我的mapping的定义为:”index” => “not_analyzed”
当然,index部分,您可以不定义,直接用默认的方式,是会被分词的。mapping类似于一个表定义。
当model建立好,您如果定义了mapping,那么您需要执行一下方法updateMapping(),让es建立mapping,该方法执行一次就可以了。
如果您需要在mapping中添加其他的字段,那么添加后在运行一次updateMapping()
另外需要注意的是:elasticSearch的mapping是不能删除的,建了就是建了,如果要删除,您只能删除index(相当于mysql的db),然后重建mapping,因此,您最好写一个脚本,执行es的所有model的mapping。
到这里,model就讲述完了、
配置部分如下:
'elasticsearch' => [ 'class' => 'yii\elasticsearch\Connection', 'nodes' => [ ['http_address' => '192.168.0.199:9200'], ['http_address' => '192.168.0.210:9200'], ], ],
您配置了es的集群,那么需要在http_address中把每一个节点的ip都要配置上,
我只有两个节点,那么,我只写了两个IP。
这样就完成了在Yii2中es的配置。
在命令行输入如下命令,即可查看镜像地址:
$ composer config -g repo.packagist {"type":"composer","url":"https://packagist.org","allow_ssl_downgrade":true}
也可以使用 composer config -l -g 查看所有全局配置
下面有把地址修改为中国镜像,如果中国镜像出现了问题,那么您可以还原成官方的默认地址,下面是详细。
启用中国全量镜像服务有两种方式,具体配置方法如下:
即将配置信息添加到 Composer 的全局配置文件 config.json 中。修改composer的全局配置文件(推荐方式),打开命令行并执行如下命令:
默认地址改为中国镜像地址:
composer config -g repo.packagist composer https://packagist.phpcomposer.com
中国镜像地址还原成默认地址:(注意:这个是将中国镜像还原)
composer config -g repo.packagist composer https://packagist.org
即将将配置信息添加到某个项目的 composer.json 文件中。修改当前项目的composer.json配置文件有两种方式,最后都是向文件中添加如下配置信息:
"repositories": { "packagist": { "type": "composer", "url": "https://packagist.phpcomposer.com" } }
2.1 打开命令行并进入项目的根目录(也就是 composer.json 文件所在目录),执行如下命令:
默认地址改为中国镜像地址:
composer config repo.packagist composer https://packagist.phpcomposer.com
该命令将会在当前项目中的 composer.json 文件的末尾自动添加镜像的配置信息
中国镜像地址还原成默认地址:(注意:这个是将中国镜像还原)
composer config repo.packagist composer https://packagist.org
2.2 手动向composer.json文件中添加以上信息
默认地址改为中国镜像地址:
"repositories": { "packagist": { "type": "composer", "url": "https://packagist.phpcomposer.com" } }
中国镜像地址还原成默认地址:(注意:这个是将中国镜像还原)
将url的值改为:https://packagist.org