PHP+MYSQL实现全文检索

如何使用PHP实现全文检索功能?
很多人可能马上可以想出几种方案,比如:文件检索法、采用SQL的like语句等方法,但这些方法效率都相当的低。
这里介绍一种比较高效的PHP全文检索实现方法,这就是采用MYSQL的FULLTEXT字段类型。但是MYSQL的FULLTEXT字段对中文的支持不是很好,本文也一并介绍如何通过PHP+MYSQL实现中文全文检索功能。
首先需要用到一个PHP中文分词扩展模块——SCWS,关于这个模块的安装和使用大家可以到www.ftphp.com/scws去查找相关内容(如有问题请留言)。
然后再看看mysql的fulltext字段类型的相关信息:
MySQL3.23.23之后的版本开始支持全文索引和搜索。全文索引在 MySQL 中是一个 FULLTEXT 类型索引。
FULLTEXT 索引用于 MyISAM 表,可以在 CREATE TABLE 时或之后使用 ALTER TABLE 或 CREATE INDEX 在 CHAR、VARCHAR 或 TEXT 列上创建。对于大的数据库,将数据装载到一个没有 FULLTEXT 索引的表中,然后再使用 ALTER TABLE (或 CREATE INDEX) 创建索引,这将是非常快的。将数据装载到一个已经有 FULLTEXT 索引的表中,将是非常慢的。

MYSQL全文搜索通过 MATCH() 函数完成。
下面举一简单例子:
1、新建数据表:
CREATE TABLE fulltext_sample(copy TEXT,FULLTEXT(copy)) TYPE=MyISAM;
这里的copy就是一个fulltext类型的字段,如果建表的时候没有添加全文检索字段,也可以通过alert来添加,如:
ALTER TABLE fulltext_sample ADD FULLTEXT(copy)
2、插入数据:
INSERT INTO fulltext_sample VALUES
(‘It appears good from here’),
(‘The here and the past’),
(‘Why are we hear’),
(‘An all-out alert’),
(‘All you need is love’),
(‘A good alert’);
3、数据检索:
SELECT * FROM fulltext_sample WHERE MATCH(copy) AGAINST(‘love’);
上面就是mysql的全文检索功能,注意:在全文索引上进行搜索是不区分大小写的。

下面再看如何实现中文全文检索。
fulltext字段是以词语为单位,词语之间需要用空格隔开,而汉语的句子中各个词语之间并不会用空格隔开,因此我们需要对中文进行分词,这也就是为什么上面需要强词用到中文分词扩展模块。
但是尽管对中文进行分词,MYSQL还是不能通过MATCH来实现中文的全文检索,这需要通过一定的方法来进行转换,一个比较简单实用的方法是采用下面这个函数(当然还有更好的),它将中文进行了urlencode转换。
function q_encode($str)
{
 $data = array_filter(explode(” “,$str));
 $data = array_flip(array_flip($data));
 foreach ($data as $ss) {
  if (strlen($ss)>1 ) 
   $data_code .= str_replace(“%”,””,urlencode($ss)) . ” “;
 }
 $data_code = trim($data_code);
 return $data_code;
}
将转换过后的内容保存至事先定义好的fulltext字段。同样,在查询的时候也需要将查询的关键词进行同样方法的转换。

浅谈Docker隔离性和安全性

相信很多开发者都默认Docker这样的容器是一种沙盒(sandbox)应用,也就是说他们可以用root权限在Docker中运行随便什么应用,而Docker有安全机制能保护宿主系统。比如,有些人觉得Docker容器里面的进程跟虚拟机里面的进程一样安全;还有的人随便找个源就下载没有验证过的Docker镜像,看都不看内容就在宿主机器上尝试、学习和研究;还有一些提供PaaS服务的公司竟然允许用户向多租户系统中提交自己定制的Docker镜像。请注意,上述行为均是不安全的。
继续阅读浅谈Docker隔离性和安全性

CentOS6.7 Xen安装部署和基本测试

目录:
   1. Xen的简介
   1.1  Xen的大体结构
   1.2 Xen对VM的称呼
   1.3 Xen对CPU和内存的虚拟化过程
   1.4 Xen对IO设备的虚拟化过程
   1.5 Linux Kernel对Xen的支持
   1.6 Xen版本发布简史
   1.7 Xen的工具栈
   1.8 XenStore
   1.9  虚拟化中的四种网络模型
   1.10 Xen的安全问题导读
   2. Xen的安装及配置文件说明
   2.1.1  在CentOS6.6上运行Xen的条件
   2.1.2  Xen的配置
   2.2.1  Xen 启动DomU的配置文件说明
   2.2.1.1  如何创建一个Xen PV模式的VM 【注:HVM模式的VM创建参见试验部分】
   3. 使用libvirt实现Xen虚拟机的图形管理
   4. PV DomU的根文件系统可以以多种不同的方式安置

继续阅读CentOS6.7 Xen安装部署和基本测试

React 概览

React 的核心思想是:封装组件。

各个组件维护自己的状态和 UI,当状态变更,自动重新渲染整个组件。

基于这种方式的一个直观感受就是我们不再需要不厌其烦地来回查找某个 DOM 元素,然后操作 DOM 去更改 UI。

React 大体包含下面这些概念:

  • 组件
  • JSX
  • Virtual DOM
  • Data Flow

这里通过一个简单的组件来快速了解这些概念,以及建立起对 React 的一个总体认识。

import React, { Component } from 'react';
import { render } from 'react-dom';

class HelloMessage extends Component {
  render() {
    return <div>Hello {this.props.name}</div>;
  }
}

// 加载组件到 DOM 元素 mountNode
render(<HelloMessage name="John" />, mountNode);

组件

React 应用都是构建在组件之上。

上面的 HelloMessage 就是一个 React 构建的组件,最后一句 render 会把这个组件显示到页面上的某个元素 mountNode 里面,显示的内容就是 <div>Hello John</div>

props 是组件包含的两个核心概念之一,另一个是 state(这个组件没用到)。可以把 props 看作是组件的配置属性,在组件内部是不变的,只是在调用这个组件的时候传入不同的属性(比如这里的 name)来定制显示这个组件。

JSX

从上面的代码可以看到将 HTML 直接嵌入了 JS 代码里面,这个就是 React 提出的一种叫 JSX 的语法,这应该是最开始接触 React 最不能接受的设定之一,因为前端被“表现和逻辑层分离”这种思想“洗脑”太久了。但实际上组件的 HTML 是组成一个组件不可分割的一部分,能够将 HTML 封装起来才是组件的完全体,React 发明了 JSX 让 JS 支持嵌入 HTML 不得不说是一种非常聪明的做法,让前端实现真正意义上的组件化成为了可能。

好消息是你可以不一定使用这种语法,后面会进一步介绍 JSX,到时候你可能就会喜欢上了。现在要知道的是,要使用包含 JSX 的组件,是需要“编译”输出 JS 代码才能使用的,之后就会讲到开发环境。

Virtual DOM

当组件状态 state 有更改的时候,React 会自动调用组件的 render 方法重新渲染整个组件的 UI。

当然如果真的这样大面积的操作 DOM,性能会是一个很大的问题,所以 React 实现了一个Virtual DOM,组件 DOM 结构就是映射到这个 Virtual DOM 上,React 在这个 Virtual DOM 上实现了一个 diff 算法,当要重新渲染组件的时候,会通过 diff 寻找到要变更的 DOM 节点,再把这个修改更新到浏览器实际的 DOM 节点上,所以实际上不是真的渲染整个 DOM 树。这个 Virtual DOM 是一个纯粹的 JS 数据结构,所以性能会比原生 DOM 快很多。

Data Flow

“单向数据绑定”是 React 推崇的一种应用架构的方式。当应用足够复杂时才能体会到它的好处,虽然在一般应用场景下你可能不会意识到它的存在,也不会影响你开始使用 React,你只要先知道有这么个概念。

开发环境配置

要搭建一个现代的前端开发环境配套的工具有很多,比如 Grunt / Gulp / Webpack / Broccoli,都是要解决前端工程化问题,这个主题很大,这里为了使用 React 我们只关注其中的两个点:

  • JSX 支持
  • ES6 支持

好消息是业界领先的 ES6 编译工具 Babel 随着作者被 Facebook 招入麾下,已经内置了对 JSX 的支持,我们只需要配置 Babel 一个编译工具就可以了,配合 webpack 非常方便。

Webpack 配置 React 开发环境

Webpack 是一个前端资源加载/打包工具,只需要相对简单的配置就可以提供前端工程化需要的各种功能,并且如果有需要它还可以被整合到其他比如 Grunt / Gulp 的工作流。

安装 Webpack:npm install -g webpack

Webpack 使用一个名为 webpack.config.js 的配置文件,要编译 JSX,先安装对应的 loader: npm install babel-loader --save-dev

假设我们在当前工程目录有一个入口文件 entry.js,React 组件放置在一个 components/ 目录下,组件被 entry.js 引用,要使用 entry.js,我们把这个文件指定输出到 dist/bundle.js,Webpack 配置如下:

var path = require('path');

module.exports = {
    entry: './entry.js',
    output: {
        path: path.join(__dirname, '/dist'),
        filename: 'bundle.js'
    },
    resolve: {
        extensions: ['', '.js', '.jsx']
    },
    module: {
        loaders: [
            { test: /\.js|jsx$/, loaders: ['babel'] }
        ]
    }
}

resolve 指定可以被 import 的文件后缀。比如 Hello.jsx 这样的文件就可以直接用 import Hello from 'Hello' 引用。

loaders 指定 babel-loader 编译后缀名为 .js 或者 .jsx 的文件,这样你就可以在这两种类型的文件中自由使用 JSX 和 ES6 了。

监听编译: webpack -d --watch

更多关于 Webpack 的介绍

JSX

为什么要引入 JSX 这种语法

传统的 MVC 是将模板放在其他地方,比如 <script> 标签或者模板文件,再在 JS 中通过某种手段引用模板。按照这种思路,想想多少次我们面对四处分散的模板片段不知所措?纠结模板引擎,纠结模板存放位置,纠结如何引用模板……下面是一段 React 官方的看法:

We strongly believe that components are the right way to separate concerns rather than “templates” and “display logic.” We think that markup and the code that generates it are intimately tied together. Additionally, display logic is often very complex and using template languages to express it becomes cumbersome.

简单来说,React 认为组件才是王道,而组件是和模板紧密关联的,组件模板和组件逻辑分离让问题复杂化了。显而易见的道理,关键是怎么做?

所以就有了 JSX 这种语法,就是为了把 HTML 模板直接嵌入到 JS 代码里面,这样就做到了模板和组件关联,但是 JS 不支持这种包含 HTML 的语法,所以需要通过工具将 JSX 编译输出成 JS 代码才能使用。

JSX 是可选的

因为 JSX 最终是输出成 JS 代码来表达的,所以我们可以直接用 React 提供的这些 DOM 构建方法来写模板,比如一个 JSX 写的一个链接:

<a href="http://facebook.github.io/react/">Hello!</a>

用 JS 代码来写就成这样了:

React.createElement('a', {href: 'http://facebook.github.io/react/'}, 'Hello!')

你可以通过 React.createElement 来构造组件的 DOM 树。第一个参数是标签名,第二个参数是属性对象,第三个参数是子元素。

一个包含子元素的例子:

var child = React.createElement('li', null, 'Text Content');
var root = React.createElement('ul', { className: 'my-list' }, child);
React.render(root, document.body);

对于常见的 HTML 标签,React 已经内置了工厂方法:

var root = React.DOM.ul({ className: 'my-list' },
             React.DOM.li(null, 'Text Content')
           );

所以 JSX 和 JS 之间的转换也很简单直观,用 JSX 的好处就是它基本上就是 HTML(后面会讲到有一些小差异),对于构造 DOM 来说我们更熟悉,更具可读性。

关于 JSX 映射成 JS 对象,也就是 Virtual DOM 的内部描述,参见Virtual DOM Terminology,如果你不想使用 JSX,直接使用 JS 就是用这里面提到的接口方法。

使用 JSX

利用 JSX 编写 DOM 结构,可以用原生的 HTML 标签,也可以直接像普通标签一样引用 React 组件。这两者约定通过大小写来区分,小写的字符串是 HTML 标签,大写开头的变量是 React 组件。

使用 HTML 标签:

import React from 'react';
import { render } from 'react-dom';

var myDivElement = <div className="foo" />;
render(myDivElement, document.getElementById('mountNode'));

HTML 里的 class 在 JSX 里要写成 className,因为 class 在 JS 里是保留关键字。同理某些属性比如 for 要写成 htmlFor

使用组件:

import React from 'react';
import { render } from 'react-dom';
import MyComponent from './MyComponet';

var myElement = <MyComponent someProperty={true} />;
render(myElement, document.body);

使用 JavaScript 表达式

属性值使用表达式,只要用 {} 替换 "":

// Input (JSX):
var person = <Person name={window.isLoggedIn ? window.name : ''} />;
// Output (JS):
var person = React.createElement(
  Person,
  {name: window.isLoggedIn ? window.name : ''}
);

子组件也可以作为表达式使用:

// Input (JSX):
var content = <Container>{window.isLoggedIn ? <Nav /> : <Login />}</Container>;
// Output (JS):
var content = React.createElement(
  Container,
  null,
  window.isLoggedIn ? React.createElement(Nav) : React.createElement(Login)
);

注释

在 JSX 里使用注释也很简单,就是沿用 JavaScript,唯一要注意的是在一个组件的子元素位置使用注释要用 {} 包起来。

var content = (
  <Nav>
      {/* child comment, put {} around */}
      <Person
        /* multi
           line
           comment */
        name={window.isLoggedIn ? window.name : ''} // end of line comment
      />
  </Nav>
);

HTML 转义

React 会将所有要显示到 DOM 的字符串转义,防止 XSS。所以如果 JSX 中含有转义后的实体字符比如 &copy; (©) 最后显示到 DOM 中不会正确显示,因为 React 自动把 &copy; 中的特殊字符转义了。有几种解决办法:

  • 直接使用 UTF-8 字符 ©
  • 使用对应字符的 Unicode 编码,查询编码
  • 使用数组组装 <div>{['cc ', <span>&copy;</span>, ' 2015']}</div>
  • 直接插入原始的 HTML
<div dangerouslySetInnerHTML={{__html: 'cc © 2015'}} />

自定义 HTML 属性

如果在 JSX 中使用的属性不存在于 HTML 的规范中,这个属性会被忽略。如果要使用自定义属性,可以用 data- 前缀。

可访问性属性的前缀 aria- 也是支持的。

支持的标签和属性

如果你要使用的某些标签或属性不在这些支持列表里面就可能被 React 忽略,必须要使用的话可以提 issue,或者用前面提到的 dangerouslySetInnerHTML