Yii2 Mongodb 生成递增id的方法

 

代码如下:

public static function increament($tablename){
    
    $coll = Yii::$app->mongodb->getCollection("ids");
    $update = array('?inc'=>array('id'=>1));
    $query = array('name'=>$tablename);
    $command = array(
      'findandmodify'=>'ids', 'update'=>$update,
      'query'=>$query, 'new'=>true, 'upsert'=>true
      );
    
    $result = $coll->mongoCollection->db->command($command);
    $id = $result['value']['id'];
    
    $current_id = (int)$id->value;
    Global $current_id;
    return $current_id;
  }

使用的时候直接 $dd = CID::increament(‘xxx’);即可获取到递增的id,

在一些场景,插入压力不是很多,但是很需要递增id的场景可以使用mongodb的这种递增id的方式,上面的写法是在yii2中使用的写法,如果不在yii2中使用mongodb的递增字段,则可以使用下面的代码:

function increament($m,$database_name,$collection_name){
  
  $ids = "ids";
  $db_name = "tracedb";
  $db = $m->selectDB($db_name);
  //$col = $m->selectDB($db_name)->$ids;
  
  $query = array('name'=>$collection_name);
  $update = array('$inc'=>array('id'=>1));
  $result = $db->command(
            array(
            "findandmodify" => $ids,
            "query" => $query,
            "update" => $update,
            'new'=>true,
            'upsert'=>true
            )
          );

  return $result['value']['id'];
  
  

}

 

Yii2 ElasticSearch aggregate (group) 的例子

直接上代码:

public function actionCountry(){
    $size = 5000;
    $name = 'country_code';
    $type = 'terms';
    $options = [
      'field' => 'country_code',
      'size'  => $size,
    ];
    
    $data = WholeCountryData::find()
        //->limit(5000)
        //->offset(0)
        ->asArray()  
        ->addAgg($name, $type, $options)
        ->createCommand()
        ->search();
    $agg_data = $data['aggregations'];
    $buckets  = $agg_data['country_code']['buckets'];
    //var_dump($agg_data);exit;
    $country_code_arr = \yii\helpers\BaseArrayHelper::getColumn($buckets,'key');
    var_dump($country_code_arr);
    
  }

我想要统计的是country_code 出现的次数,通过yii2的ElasticSearch扩展,上面的例子满足我的需要。

yii2 使用apidoc生成技术文档

yii2 的apidoc生成文档还是蛮好用的。
首先说一下这个玩意是干什么的,就是用来生成技术文档,效果可以查看:http://www.fecshop.com/doc/fecshop-guide/cn-1.0/guide-index.html#

1.需要安装yii2,参看文章:

Yii2 – 安装高级模板 advanced project template

2.然后安装doc 插件

2.1在安装的yii2根目录下面执行:

composer require --prefer-dist yiisoft/yii2-apidoc

2.2或者在composer.json中添加:

"yiisoft/yii2-apidoc": "~2.1.0"

然后执行:composer update

可能会报错,如果报错,将上面的改成:

yiisoft/yii2-apidoc": "~2.0.0"

安装成功就可以使用了

3.写md文件

可以看下面的第四部的路径,md文件存放的地址: /www/web/develop/fecshop/doc/fecshop-guide/cn-1.0,那么我们在这个路径下面新建2个比较重要的md文件

README.md 和 index.md

README.md 是左侧菜单部分

index.md 是guide-index.html页面,一般和README.md一样,用来做首页菜单索引,当然也可以添加自己想要的内容

生成的效果可以参看:

http://www.fecshop.com/doc/fecshop-guide/cn-1.0/guide-index.html#

展示一个demo:

README.md:

FecShop 文档说明
===============================

版权所有。

2016 (c) FecShop Software LLC。

目前进度
-----
*  [Fecshop 开发进度](fecshop-jindu.md)
*  [Fecshop 开发LOG](fecshop-jindu-log.md)

关于与安装
-----

*  [Fecshop 关于-架构特点](fecshop-about-fecshop.md)
*  [Fecshop 关于-功能介绍](fecshop-about-function.md)
*  [Fecshop 关于-系统结构](fecshop-about-system-contruct.md)
*  [Fecshop 安装与初始配置](fecshop-install.md)

Fecshop配置
-----------

*  [Fecshop 配置-配置结构](fecshop-init-config-construction.md)
*  [Fecshop 配置-Yii2配置](fecshop-init-config-yii2.md)
*  [Fecshop 配置-fecshop配置](fecshop-init-config-advanced.md)

index.md

FecShop 文档说明
===============================

版权所有。

2016 (c) FecShop Software LLC。


关于与安装
-----

*  [Fecshop 关于-架构特点](fecshop-about-fecshop.md)
*  [Fecshop 关于-功能介绍](fecshop-about-function.md)
*  [Fecshop 关于-系统结构](fecshop-about-system-contruct.md)
*  [Fecshop 安装-composer](fecshop-install.md)
*  [Fecshop 安装-初始配置](fecshop-init-config.md)



功能介绍
--------
*  [Fecshop 功能概叙](fecshop-feature-summary.md)
*  [Fecshop Url自定义](fecshop-feature-url-custom.md)
*  [Fecshop 多语言](fecshop-feature-mutil-languages.md)
*  [Fecshop 多store](fecshop-feature-mutil-stores.md)
*  [Fecshop 多货币](fecshop-feature-mutil-currency.md)
*  [Fecshop 多模板](fecshop-feature-mutil-themes.md)
*  [Fecshop 多入口](fecshop-feature-mutil-entrances.md)
*  [Fecshop 配置层](fecshop-feature-config.md)
*  [Fecshop 模块层](fecshop-feature-modules.md)
*  [Fecshop Block层](fecshop-feature-block.md)
*  [Fecshop 服务层](fecshop-feature-component-services.md)
*  [Fecshop 独立功能块](fecshop-feature-independent-block.md)
*  [Fecshop 权限管理](fecshop-feature-role.md)
*  [Fecshop 缓存管理](fecshop-feature-cache.md)
*  [Fecshop 脚本管理](fecshop-feature-script.md)
*  [Fecshop 后台日志](fecshop-feature-admin-log.md)
*  [Fecshop 重写功能](fecshop-feature-rewrite.md)
*  [Fecshop 升级](fecshop-feature-upgrade.md)

在README.md文件里面你可以看到,在括号里面的文件  ,譬如 fecshop-jindu.md

你需要在 /www/web/develop/fecshop/doc/fecshop-guide/cn-1.0下新建括号里面的md文件,然后在里面写内容就行了,譬如:

关于 Fecshop 的框架特点
=======================

Fecshop 全称为Fancy ECommerce Shop,是一款优秀的开源电商系统,遵循[OSL3.0协议](http://www.oschina.net/question/28_8527),
目的是为了方便yii2用户快速的
开发商城,Fecshop作为一款可以持续性发展的商城系统,
在框架层面有以下特性:

1. 由于商城系统的复杂性,原始的框架MVC结构,显的有点力不从心,Fecshop框架
加入了[Block层](fecshop-feature-block.md),
Controller层只负责调度, Model只负责数据库映射,中间的处理逻辑由block来完成,View层
负责显示,这样各司其职, 以免造成controller文件过于庞大。

2. 加入[独立功能块](fecshop-feature-independent-block.md),有点类似Yii2的Widget,目的是为了让一些侧栏公用块
可以通过配置的方式
添加,同时,还可以具有设置缓存的功能,譬如侧栏的产品浏览记录,
newsletter等独立显示块可能在很多
页面用到,通过独立功能块可以配置方便的载入。

 

 

4. 写个sh脚本用来生成文档,当然,您可以可以直接运行里面的代码,不过用sh运行比较方便:

#!/bin/sh

rm -rf /www/web/online-2/www.fecshop.com/appfront/web/doc/fecshop-guide/cn-1.0/*
/www/web/develop/fecshopdoc/vendor/bin/apidoc  guide   /www/web/develop/fecshop/doc/fecshop-guide/cn-1.0   /www/web/online-2/www.fecshop.com/appfront/web/doc/fecshop-guide/cn-1.0/  --interactive=0

md文件存放的地址为: /www/web/develop/fecshop/doc/fecshop-guide/cn-1.0

md生成的html的地址为:/www/web/online-2/www.fecshop.com/appfront/web/doc/fecshop-guide/cn-1.0/

 

然后nginx 指向/www/web/online-2/www.fecshop.com/appfront/web

然后访问http://127.0.0.1/doc/fecshop-guide/cn-1.0/guide-index.html

就可以看到效果了

效果演示:http://www.fecshop.com/doc/fecshop-guide/cn-1.0/guide-index.html#

 

最后,您可能感觉样式不好,想改一下,可以修改;

vendor/bower/bootstrap/dist/css/bootstrap.css

或者添加文件,覆盖这个文件里面的css内容即可。

如果您要大改,把页面底部彻底换掉,可以到

/www/web/tadoc/vendor/yiisoft/yii2-apidoc/templates

这里找对应的代码,然后改掉html内容,在添加css内容等等

 

js 代码: 通过js 得到去掉前缀的域名

js 代码如下:

<script>
domain = document.domain;
domain = domain.match(/[^\.]*\.[^.]*$/)[0];
</script>

如果当前域名为http://fancyecommerce.com 返回 fancyecommerce.com

如果当前域名为http://www.fancyecommerce.com 返回 fancyecommerce.com

如果当前域名为http://xxxx.fancyecommerce.com 返回 fancyecommerce.com

Yii2 elasticSearch 多值查询 和 查询数组字段

Yii2 elasticSearch 多值查询的例子,相当于关系型数据库的in查询

$should = [];
if(is_array($customers) && !empty($customers)){
  foreach($customers as $one){
    $should[] = ['term' => ['customer_id' => $one['customer_id']]];
  }
}
$filter_arr['bool']['should'] = $should;
$result = $obj::find()->filter($filter_arr)
    ->query($query_arr)
    ->asArray()
    ->limit(0)
    ->offset(33)
    ->all();
$data = BaseArrayHelper::getColumn($result, '_source');

查询数组字段,$filter的定义如下:

$filter_arr = [
        'bool' => [
          'must' => [
            ['term' => ['emails' => $email],]
          ]
        ],
      ];

 

 

elasticSearch 批量传递数据,存在数据丢失的原因

elasticSearch 如果字段要做全量匹配,也就是像mysql那样,而不是分词模糊匹配,那么需要建立mapping   加入not_analysised ,这个可以参考之前的文章。

然后我重新传递数据的时候,发现数据存在丢失,最后找出来了原因:

1.如果是多维数组,那么需要建立mapping,不然无法传递数据,但是如果是一维数组,则没有问题,因此,如果是多维数组,可以序列化成字符串存储

2.如果一个字段定义成string,如果长度太长,几千的字符,那么就会保存不了,长度过长,我就是把多维数组序列化后,长度太长无法保存到elasticSearch中,最后,我把多维数组里面的每一个子项进行序列化,然后以一维数组的方式存储,算是解决了这个问题。

elasticSearch在使用的时候,还是有一些坑,需要多练习,多观察一些数据,是否丢失,是否准确等等。

Yii2 – elasticSearch 新建mapping操作

在一些需要完全匹配,或者其他的一些情况,需要建立mapping,这个有点类似mysql的表定义

ActiveRecord的定义:

<?php

namespace appadmin\code\Ta\models\elasticSearch;

use yii\elasticsearch\ActiveRecord;

class TraceData extends ActiveRecord
{
  public static $currentIndex;
  
  # 定义db链接
  public static function getDb()
  {
    return \Yii::$app->get('elasticsearch_TA');
  }
  
  # 不同的website 使用的是不同的db ,使用前需要先初始化
  # db的名字
  public static function initDb($website_id){
    if($website_id){
      self::$currentIndex = 'ta'."_".$website_id;
    }
  }
  
  
  
  # db
  public static function index()
  {
    return self::$currentIndex;
  }
  # table
  public static function type()
  {
    return 'trace_data';
  }
  
   public function attributes()
    {
        $mapConfig = self::mapConfig();
    return array_keys($mapConfig['properties']);
    }
  
  public static function mapConfig(){
    return [
      'properties' => [
        'id'				=> ['type' => 'string',"index" => "not_analyzed"],
        'ip'				=> ['type' => 'string',"index" => "not_analyzed"],
        'service_date_str'	=> ['type' => 'string',"index" => "not_analyzed"],
        'service_datetime'	=> ['type' => 'string',"index" => "not_analyzed"],
        'service_timestamp'	=> ['type' => 'integer',"index" => "not_analyzed"],
        'devide' 			=> ['type' => 'string',"index" => "not_analyzed"],
        'user_agent' 		=> ['type' => 'string',"index" => "not_analyzed"],
        'browser_name' 		=> ['type' => 'string',"index" => "not_analyzed"],
        'browser_version'	=> ['type' => 'string',"index" => "not_analyzed"],
        'browser_date'		=> ['type' => 'string',"index" => "not_analyzed"],
        'browser_lang'		=> ['type' => 'string',"index" => "not_analyzed"],
        'operate' 			=> ['type' => 'string',"index" => "not_analyzed"],
        'operate_relase'	=> ['type' => 'string',"index" => "not_analyzed"],
        'domain' 			=> ['type' => 'string',"index" => "not_analyzed"],
        'url'				=> ['type' => 'string',"index" => "not_analyzed"],
        'title'				=> ['type' => 'string',"index" => "not_analyzed"],
        'refer_url'			=> ['type' => 'string',"index" => "not_analyzed"],
        'first_referrer_domain'	=> ['type' => 'string',"index" => "not_analyzed"],
        'is_return'			=> ['type' => 'integer',"index" => "not_analyzed"],
        'uuid'				=> ['type' => 'string',"index" => "not_analyzed"],
        'device_pixel_ratio'=> ['type' => 'string',"index" => "not_analyzed"],
        'resolution'		=> ['type' => 'string',"index" => "not_analyzed"],
        'color_depth'		=> ['type' => 'string',"index" => "not_analyzed"],
        'website_id'		=> ['type' => 'integer',"index" => "not_analyzed"],
        'sku'				=> ['type' => 'string',"index" => "not_analyzed"],
        'country_code'		=> ['type' => 'string',"index" => "not_analyzed"],
        'country_name'		=> ['type' => 'string',"index" => "not_analyzed"],
        
        'order_status' 		=> ['type' => 'string',"index" => "not_analyzed"],
        'cart' 				=> ['type' => 'string',"index" => "not_analyzed"],
        'order'				=> ['type' => 'string',"index" => "not_analyzed"],
        'category'			=> ['type' => 'string',"index" => "not_analyzed"],
        'login_email'		=> ['type' => 'string',"index" => "not_analyzed"],
        'register_email'	=> ['type' => 'string',"index" => "not_analyzed"],
        'search'			=> ['type' => 'string',"index" => "not_analyzed"],
        'currency'			=> ['type' => 'string',"index" => "not_analyzed"],
        'url_new'			=> ['type' => 'string',"index" => "not_analyzed"],
        'stay_seconds'		=> ['type' => 'integer',"index" => "not_analyzed"],
        'first_visit_this_url'	=> ['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();
  }
  
  
  
}

使用:

public function actionMapping($websiteIds){
    $arr = explode(",",$websiteIds);
    foreach($arr as $website_id){
      TraceData::initDb($website_id);
      TraceData::updateMapping();
      $map = TraceData::getMapping();
      var_dump($map);
    }
}

通过updateMapping来更新mapping

通过getMapping得到定义好的mapping

在这里的一个坑就是:在添加表(type)mapping的时候,需要提前定义Index(相当于mysql的db),才能添加type(相当于表),否则添加不上,或者报错。

其他资料:
https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html

http://www.open-open.com/lib/view/open1455452874636.html

Yii2 – 批量插入数据到 elasticSearch

elasticSearch 是目前来说,最强大的开源搜索引擎,对于一些搜索,放到ElasticSearch中,速度会快很多,当然,这个玩意也是非常消耗资源。

下面是,使用yii2,将数据批量导入到ES中,单行插入的效率太低,使用批量插入,速度还是可以。

安装ElasticSearch 这个参看

安装ElasticSearch ,以及在yii2中的使用

2. 安装yii2-ElasticSearch插件

https://github.com/yiisoft/yii2-elasticsearch

3. 配置

'elasticsearch_TA' => [
    'class' => 'yii\elasticsearch\Connection',
    'nodes' => [
        ['http_address' => '192.168.0.199:9200'],
        ['http_address' => '192.168.0.210:9200'],
    ],
],

4.使用

传递数据,我们还是用shell 脚本来传递数据 /appta/shell/customer/syncCustomerDataToEs.sh

#!/bin/sh

DIR=$(cd `dirname $0`; pwd)
# sync mongodb to elasticsearch
echo 'sync custom data to es'
processDate=$1
websiteIds=$2

arr=$(echo $websiteIds|tr "," "\n");
for website_id in $arr; do
  echo "website_id:".$website_id;
  variable=`$DIR/../../../yii ta/migrate/elasticsearch/customerdatapagecount $processDate $website_id`
  echo "$variable.."
  for (( i=1; i<=$variable; i++ ))
  do 
    $DIR/../../../yii ta/migrate/elasticsearch/customerdata $processDate $website_id $i 
    echo "Page $i done"
  done
done







controller文件:

<?php
namespace appadmin\code\Ta\console\migrate;
use Yii;
use appadmin\code\Ta\models\WebsiteBaseInfo;
use yii\console\Controller;
use appadmin\code\Ta\helper\mongoDb as MongoDb;
use appadmin\code\Ta\models\mongo\CustomerData as MgCustomerData;
use appadmin\code\Ta\models\elasticSearch\CustomerData as EsCustomerData;

use appadmin\code\Ta\models\mongo\TraceData as MgTraceData;
use appadmin\code\Ta\models\elasticSearch\TraceData as EsTraceData;


class ElasticsearchController extends Controller
{
  public $numPerPage = 1000;
  //public $dbName = "ta_".$processDate;
  //public $collName;
  
  public function initParam($processDate,$website_id){
    //$thidbName = "ta_".$processDate;
    $collName = "ta_".$website_id."_customer_data";
    //echo $processDate;exit;
    MongoDb::setDbByDate($processDate);
    MgCustomerData::initCollName($website_id);
    MgTraceData::initCollName($website_id);
  }
  # customer data  数据的总页数
  public function actionCustomerdatapagecount($processDate,$website_id){
    $this->initParam($processDate,$website_id);
    $count =  MgCustomerData::find()->count();
    //var_dump(MgCustomerData::getDb());
    //echo $count;exit;
    echo ceil($count/$this->numPerPage);
  }
  # 同步customer data的数据到ElasticSearch
  public function actionCustomerdata($processDate,$website_id,$pageNum){
    $this->initParam($processDate,$website_id);
    $skip = $this->numPerPage * ($pageNum - 1);
    $data = MgCustomerData::find()
        ->asArray()
        ->limit($this->numPerPage)
        ->offset($skip)
        ->all();
    $arr = [];
    $i = 0;
        
    if(is_array($data) && !empty($data )){
      $elasticsearch = Yii::$app->elasticsearch_TA;
      $bulkclient = $elasticsearch->createBulkCommand();
      //EsCustomerData::initDb($website_id);
      $index_name = 'ta_'.$website_id;
      $one_day_type = 'customer_data';
      //$EsCustomerDataOne = EsCustomerData::findOne($a['_id']);
      foreach($data  as $one){
        $i++;
        $a = [];
        $a['id'] = $one['_id'];
        $value = $one['value'];
        if(is_array($value) && !empty($value )){
          foreach($value  as $k => $v){
            if($k == 'data'){
              //var_dump($v);
              $v = serialize($v);
            }
            $a[$k] = $v;
          }
        }
        
        $bulkclient->addAction(array(
          'index' => array(
            '_index'=> $index_name,
            '_type' => $one_day_type,
            '_id' 	=> $one['_id'],
          )
        ), $a);
        /*
        # 保存数据到ES
        EsCustomerData::initDb($website_id);
        $EsCustomerDataOne = EsCustomerData::findOne($a['_id']);
        if(!$EsCustomerDataOne){
          $EsCustomerDataOne = new EsCustomerData;
          $EsCustomerDataOne->setPrimaryKey($a['_id']);
        }
        $EsCustomerDataOne->id = $a['_id'];
        $attributes = $EsCustomerDataOne->attributes();
        foreach($a as $k=>$v){
          if(in_array($k,$attributes)){
            if($k == 'data'){
              //var_dump($v);
              $v = serialize($v);
            }
            $EsCustomerDataOne[$k] = $v;
          }
        }
        $mtime=explode(' ',microtime());
        $startTime=$mtime[1]+$mtime[0];        
        
        $EsCustomerDataOne->save();
        $mtime=explode(' ',microtime());
        $endTime=$mtime[1]+$mtime[0];        
        echo "chaju_time :($i)".($endTime-$startTime)."\n"; 
        //$arr[] = $a; 
        */
      }
      $bulkclient->execute();
    }
    
    
  }
    
  # customer data  数据的总页数
  public function actionTracedatapagecount($processDate,$website_id){
    $this->initParam($processDate,$website_id);
    $count =  MgTraceData::find()->count();
    //var_dump(MgCustomerData::getDb());
    //echo $count;exit;
    echo ceil($count/$this->numPerPage);
  }
  # 同步customer data的数据到ElasticSearch
  public function actionTracedata($processDate,$website_id,$pageNum){
    $this->initParam($processDate,$website_id);
    $skip = $this->numPerPage * ($pageNum - 1);
    $data = MgTraceData::find()
        ->asArray()
        ->limit($this->numPerPage)
        ->offset($skip)
        ->all();
    $arr = [];
    $i = 0;
        
    if(is_array($data) && !empty($data )){
      $elasticsearch = Yii::$app->elasticsearch_TA;
      $bulkclient = $elasticsearch->createBulkCommand();
      //EsCustomerData::initDb($website_id);
      $index_name = 'ta_'.$website_id;
      $one_day_type = 'trace_data';
      //$EsCustomerDataOne = EsCustomerData::findOne($a['_id']);
      foreach($data  as $one){
        $i++;
        $a = [];
        
        if(is_array($one) && !empty($one )){
          foreach($one  as $k => $v){
            $a[$k] = $v;
          }
        }
        $a['id'] = $a['_id'];
        unset($a['_id']);
        
        $bulkclient->addAction(array(
          'index' => array(
            '_index'=> $index_name,
            '_type' => $one_day_type,
            '_id' 	=> $one['_id'],
          )
        ), $a);
        
      }
      $bulkclient->execute();
    }
    
    
  }	
    
    
    
    
    
    
    
    
    
    
    
}

appadmin\code\Ta\models\mongo\CustomerData

<?php  
# 商家SELLER 和  对应的 SELLERID 的设置。 
namespace appadmin\code\Ta\models\mongo; 
use yii\mongodb\ActiveRecord;
use fec\helpers\CDate;
use fec\helpers\CConfig;
use Yii;
use appadmin\code\Ta\helper\mongoDb;
# use appadmin\code\Ta\models\mongo\CustomerData; 
class CustomerData extends ActiveRecord  
{  
  
  public static $_collectionName;
  
  # 定义db
  public static function getDb()
    {
    return \Yii::$app->get('mongodb_ta_date');
    }
  
  
  
  # 定义collection name  
    public static function collectionName()  
    {  
        return self::$_collectionName;  
    }  
  
  
  
  
  public static function initCollName($website_id){
    self::$_collectionName = "ta_".$website_id."_customer_data";
  }
  
  
  public function attributes()
    {
        // path mapping for '_id' is setup to field 'id'
        return [
      '_id', 
      'value',
      
    ];
    }
  
  
}  

appadmin\code\Ta\models\ElasticSearch\CustomerData

<?php

namespace appadmin\code\Ta\models\elasticSearch;

use yii\elasticsearch\ActiveRecord;

class CustomerData extends ActiveRecord
{
  public static $currentIndex;
  
  # 定义db链接
  public static function getDb()
  {
    return \Yii::$app->get('elasticsearch_TA');
  }
  
  # 不同的website 使用的是不同的db ,使用前需要先初始化
  # db的名字
  public static function initDb($website_id){
    //echo 888;
    if($website_id){
      //echo 999;
      self::$currentIndex = 'ta'."_".$website_id;
      //echo self::$currentIndex;
      //echo 3;
    }
  }
  
  
  
  # db
  public static function index()
  {
    return self::$currentIndex;
  }
  # table
  public static function type()
  {
    return 'customer_data';
  }
  
   public function attributes()
    {
        // path mapping for '_id' is setup to field 'id'
        return [
      'id',
      
      'uuid',
      'customer_id',
      'pv',
      
      'ip',
      'service_date_str',
      'service_datetime',
      'service_timestamp',
      'devide',
      'user_agent',
      'browser_name',
      'browser_version',
      'browser_date',
      'browser_lang',
      'operate',
      'operate_relase',
      'domain',
      'url',
      'title',
      'refer_url',
      'first_referrer_domain',
      'is_return',
      'uuid',
      'device_pixel_ratio',
      'resolution',
      'color_depth',
      'website_id',
      'sku',
      'country_code',
      'country_name',
      
      'data',
      
      'order_status',
      'cart',
      'order',
      'category',
      'login_email',
      'register_email',
      'search',
      'currency',
      'stay_seconds',
    ];
    }
  
  
  
}

 

 

linux防火墙 – apf 安装 ,配置,使用

apf是一款比较好用的linxu防火墙,用它来设置iptables等是一个比较好的工具,线上一般免费版,很多使用这个,下面说一下他的安装与配置

wget http://www.rfxn.com/downloads/apf-current.tar.gz  
tar -xvzf apf-current.tar.gz  
cd apf-9.7-2/  
./install.sh  
  
[root@iZ942k2d5ezZ apf-9.7-2]# ./install.sh  
Installing APF 9.7-2: Completed.  
  
Installation Details:  
  Install path:         /etc/apf/  
  Config path:          /etc/apf/conf.apf  
  Executable path:      /usr/local/sbin/apf  
  
Other Details:  
  Listening TCP ports: 22,80,100,3306,6379,27017  
  Listening UDP ports: 123,636  
  Note: These ports are not auto-configured; they are simply presented for information purposes. You must manually configure all port options.

到上面就安装成功了

启动

/etc/init.d/apf start  
chkconfig apf on

二,配置apf

vim /etc/apf/conf.apf   一般按照下面的配置好,然后apf -f(或者apf -r) 刷新一下就行了

IG_TCP_CPORTS="21,22,80,443,3306,8080"   //设置服务器允许被访问的TCP端口    
IG_UDP_CPORTS="53"                       //设置服务器允许被访问的UDP端口    
EG_TCP_CPORTS="21,25,80,443,43,2089"     //设置服务器允许对外访问的TCP端口    
EG_UDP_CPORTS="20,21,53"                 //设置服务器允许对外访问的UDP端口    
   
DEVEL_MODE="1" 改为 DEVEL_MODE="0"    
DLIST_SPAMHAUS="0" 改为 DLIST_SPAMHAUS="1"    
DLIST_DSHIELD="0" 改为 DLIST_DSHIELD="1"

配置过程中要注意以下几点:
1,根据不同的服务器开放不同的端口,web服务器根mysql服务器开放的端口肯定不一样。
2,DEVEL_MODE=”1″表示在调试模式下,每五分钟重调配置,这样能避免因为错误的配置而使服务器崩溃。
3,设置只通许192.168.1.139远程连接22端口

// 在/etc/apf/allow_hosts.rules添加如下信息:    
tcp:in:d=22:s=192.168.1.139    
out:d=22:d=192.168.1.139    
    
// 在/etc/apf/deny_hosts.rules添加如下信息:    
tcp:in:d=22:s=0/0    
out:d=22:d=0/0

开始的时候,我以为只要在allow_hosts.rules里面加就行了,改过一后,我换了一个IP,已然可以连接,搞得我很无语。后在deny_hosts.rules加上了上面的规则后,在连接时就提示超时了。allow_hosts.rules和deny_hosts.rules里面都加了规则后,重起apf会提示配置成功的信息,偶然发现的。

apf(12234): {trust} allow outbound 192.168.1.139 to port 22    
apf(12234): {trust} allow inbound tcp 192.168.1.139 to port 22

三:apf常用命令

apf -s  // 启动APF防火墙    
apf -r  // 重启APF防火墙    
apf -f  // 刷新APF防火墙配置文件    
apf -l  // 列出APF的过虑规则    
apf -t  // APF的日志信息。    
apf -e  // 将域名解释加入信认规则    
apf -a  // 将IP/IP段添加到白名单    
apf -d  // 将IP/IP段添加到黑名单    
apf -u  // 将IP/IP段从白/黑名单中删除    
apf -o  // 将IP/IP段从白/黑名单中删除

常用端口:

21/tcp       //ftp    
22/tcp       //ssh    
25/tcp       //smtp    
53/udp       //dns    
80/tcp       //http    
110/tcp      //pop3    
143/tcp      //imap    
443/tcp      //https    
993/tcp      //imaps    
995/tcp      //pop3    
3306/tcp     //mysql    
5432/tcp     //postgresql

 

其他:
IG_TCP_CPORTS=”21,22,80,443,3306,8080″   //设置服务器允许被访问的TCP端口

IG_UDP_CPORTS=”53″                       //设置服务器允许被访问的UDP端口

EG_TCP_CPORTS=”21,25,80,443,43,2089″     //设置服务器允许对外访问的TCP端口

EG_UDP_CPORTS=”20,21,53″                 //设置服务器允许对外访问的UDP端口

DEVEL_MODE=”1″ 改为 DEVEL_MODE=”0″

DLIST_SPAMHAUS=”0″ 改为 DLIST_SPAMHAUS=”1″

DLIST_DSHIELD=”0″ 改为 DLIST_DSHIELD=”1″

配置过程中要注意以下几点:

1,根据不同的服务器开放不同的端口。

2,DEVEL_MODE=”1″表示在调试模式下,每五分钟重调配置,这样能避免因为错误的配置而使服务器崩溃。

3,设置只通许192.168.1.139远程连接22端口

// 在/etc/apf/allow_hosts.rules添加如下信息:

tcp:in:d=22:s=192.168.1.139

out:d=22:d=192.168.1.139

// 在/etc/apf/deny_hosts.rules添加如下信息:

tcp:in:d=22:s=0/0

out:d=22:d=0/0

开始的时候,我以为只要在allow_hosts.rules里面加就行了,改过一后,我换了一个IP,已然可以连接,搞得我很无语。后在 deny_hosts.rules加上了上面的规则后,在连接时就提示超时了。allow_hosts.rules和deny_hosts.rules里 面都加了规则后,重起apf会提示配置成功的信息,偶然发现的。

apf(12234): {trust} allow outbound 192.168.1.139 to port 22

apf(12234): {trust} allow inbound tcp 192.168.1.139 to port 22

三,apf的常用命令

apf -s  // 启动APF防火墙

apf -r  // 重启APF防火墙

apf -f  // 刷新APF防火墙配置文件

apf -l  // 列出APF的过虑规则

apf -t  // APF的日志信息。

apf -e  // 将域名解释加入信认规则

apf -a  // 将IP/IP段添加到白名单

apf -d  // 将IP/IP段添加到黑名单

apf -u  // 将IP/IP段从白/黑名单中删除

apf -o  // 将IP/IP段从白/黑名单中删除

四,常用端口列表

21/tcp       //ftp

22/tcp       //ssh

25/tcp       //smtp

53/udp       //dns

80/tcp       //http

110/tcp      //pop3

143/tcp      //imap

443/tcp      //https

993/tcp      //imaps

995/tcp      //pop3

3306/tcp     //mysql

5432/tcp     //postgresql