読者です 読者をやめる 読者になる 読者になる

UNIX的なアレ

UNIX的なこととかいろいろ

CakePHPからToritonnの全文検索を使う方法

CakePHP PHP

お手軽につかえる検索エンジンとして、SennaMySQLで作られたToritonnがありますね。
弊社のWebサービス「nanapi」でも検索エンジンには、Toritonnを使っています。MySQLベースなので、CakePHPActiveRecordがつかえて便利です。ただ、Toritonn使うときはSQLが拡張されているためちょっと工夫が必要です。
今回はCakePHPからToritonnを使うコツを紹介します。

テーブルを作成する

まずはテーブルを作成しましょう。本家のサイトのあるようにとりあえずはこんな感じで。

  CREATE TABLE search (
    id INTEGER AUTO_INCREMENT,
    PRIMARY KEY (id),
    text TEXT NOT NULL,
    FULLTEXT INDEX USING NGRAM (text)
  );

全文検索を使ってみる

このテーブルに対して全文検索をかけたいときはこんな感じです。

<?php
 $query = 'MATCH ( text ) AGAINST ("foo")' ; 

 $opt = array(
    'conditions' => array( $query ),
 );
 $search = $this->Search->find('all',$opt);

AND検索を使ってみる

次はAND検索をつかってみたい場合。BLOOLEAN MODEを使います。

<?php
 $query = 'MATCH ( text ) AGAINST ("+foo +bar" IN BLOOLEAN MODE)' ;

 $opt = array(
    'conditions' => array( $query ),
 );
 $search = $this->Search->find('all',$opt);

スコアでソートしてみる

検索結果に対してスコアをつけて、ソートさせることもできます。自動的にソートしてくれないので、ちょっと頑張らないといけません。あまりキレイな方法ではありませんが、以下のようにfieldsを指定してやることで解決。

<?php
 $query = 'MATCH ( text ) AGAINST ("foo" IN BLOOLEAN MODE)';

 $opt = array(
    'fields' => array('Search.id','Search.text',$query . ' AS score') ,
    'conditions' => array($query),
    'order' => 'score DESC',
 );
 $search = $this->Search->find('all',$opt);

マルチセクション機能を使ってソートしてみる

複数カラムにまたがったデータを検索するときは、マルチセクション機能を利用します。テーブルはこんな感じで作成してください。

  CREATE TABLE search (
    id INTEGER AUTO_INCREMENT,
    PRIMARY KEY (id),
    text1 TEXT NOT NULL,
    text2 TEXT NOT NULL,
    FULLTEXT INDEX USING NGRAM, SECTIONALIZE (text1,text2)
  );
 <?php
 $query = 'MATCH ( text1 , text2 ) AGAINST ("W1,W2 foo" IN BLOOLEAN MODE)';

 $opt = array(
    'fields' => array('Search.id','Search.text',$query . ' AS score') ,
    'conditions' => array($query),
    'order' => 'score DESC',
 );
 $search = $this->Search->find('all',$opt);

便利ですねー。