EC-CUBE 검색에 형태소 해석 엔진 (MeCab)을 구현하는 샘플

5616 단어 EC-CUBEPHPmecab
왠지 굉장한 것 같지만 굉장한 것은 MeCab을 개발한 사람으로 이 기사 자체는 큰 일 쓰지 않습니다. 형태소 해석이나 MeCab에 대해서는 이하의 wiki를 읽어 주면(자) 어딘지 모르게 이미지가 붙는다고 생각합니다.
형태소 분석
MeCab

즉 무엇?



대략적으로 말하면 「문장을 주어・술어・형용사・동사・조동사 등으로 분할하자」라는 것이 형태소 해석이라고 이해해 주십시오. 나 자신 더 이상 츳코로 이해하지 못합니다.

에서?



예를 들면 「50번의 냄비」를 검색하는 경우, 실제로는 「『50』이나『나베』에 해당하면 좋다」라고 생각하는 경우는 많을 것입니다. 그것을 일일이 스페이스에서 「50」과 「나베」로 구분하지 않고 검색할 수 있으면 편리할지도 모릅니다. 그래서 그것을 EC-CUBE에 구현해 봅시다. 라는 이야기입니다.

구현에 필요한 것



· MeCab
・EC-CUBE(2.13.3 베이스로 설명합니다)

MeCab 설치



여기 의 거리입니다.

EC-CUBE 개조



·/data/class_extends/page_extends/products/LC_Page_Products_List_Ex.php
다음 기능을 적절한 위치에 복사하십시오

/**
 * 検索条件のwhere文とかを取得
 *
 * @return array
 */
public function lfGetSearchCondition($arrSearchData)
{
    $searchCondition = array(
        'where'             => '',
        'arrval'            => array(),
        'where_category'    => '',
        'arrvalCategory'    => array()
    );

// カテゴリからのWHERE文字列取得
if ($arrSearchData['category_id'] != 0) {
    list($searchCondition['where_category'], $searchCondition['arrvalCategory']) = SC_Helper_DB_Ex::sfGetCatWhere($arrSearchData['category_id']);
}
// ▼対象商品IDの抽出
// 商品検索条件の作成(未削除、表示)
$searchCondition['where'] = SC_Product_Ex::getProductDispConditions('alldtl');

if (strlen($searchCondition['where_category']) >= 1) {
    $searchCondition['where'] .= ' AND EXISTS (SELECT * FROM dtb_product_categories WHERE ' . $searchCondition['where_category'] . ' AND product_id = alldtl.product_id)';
    $searchCondition['arrval'] = array_merge($searchCondition['arrval'], $searchCondition['arrvalCategory']);
}

// 商品名をwhere文に
$name = $arrSearchData['name'];
$name = $this->MorphologicalAnalysis($name);    // 追加箇所
$name = str_replace(',', '', $name);
// 全角スペースを半角スペースに変換
$name = str_replace(' ', ' ', $name);
// スペースでキーワードを分割
$names = preg_split('/ +/', $name);

// 分割したキーワードを一つずつwhere文に追加
foreach ($names as $val) {
    if (strlen($val) > 0) {
        $searchCondition['where']    .= ' AND ( alldtl.name ILIKE ? OR alldtl.comment3 ILIKE ?) ';
        $searchCondition['arrval'][]  = "%$val%";
        $searchCondition['arrval'][]  = "%$val%";
    }
}

// メーカーらのWHERE文字列取得
if ($arrSearchData['maker_id']) {
    $searchCondition['where']   .= ' AND alldtl.maker_id = ? ';
    $searchCondition['arrval'][] = $arrSearchData['maker_id'];
}

// 在庫無し商品の非表示
if (NOSTOCK_HIDDEN) {
    $searchCondition['where'] .= ' AND EXISTS(SELECT * FROM dtb_products_class WHERE product_id = alldtl.product_id AND del_flg = 0 AND (stock >= 1 OR stock_unlimited = 1))';
}

// XXX 一時期内容が異なっていたことがあるので別要素にも格納している。
$searchCondition['where_for_count'] = $searchCondition['where'];

return $searchCondition;


}

/**
 * 形態素解析による抜き出し
 *
 */
function MorphologicalAnalysis($txt){
    // 半角英数字のみの場合はそのまま
    if(preg_match("/^[!-~]+$/", $txt)){
        return $txt;
    }
    $mecab = new MeCab_Tagger();
    $meisi = array();
    $word = '';
    for($node=$mecab->parseToNode($txt); $node; $node=$node->getNext())
    {
        // 取捨選択が難しいので名詞のみの取得はやめ
        if( $node->getStat() != 2 && $node->getStat() != 3 && mb_strpos($node->getFeature(), '名詞', NULL, 'utf-8')===0)
        {
            $word = $node->getSurface();
            if (mb_strlen($word)>1)
            array_push($meisi, $word);  // 分解したとき1文字になるものは検索から除外
        }
    }
    return implode(" ", $meisi);
}

테스트



「50번 냄비」로 검색하면…


「오나베 50」과 「오나베 레시피 50」이 검색된다


실제로 구현해보십시오.



위의 Morphological Analysis는
・문장중의 명사만 빼낸다
・분할해 한 문자가 되는 것은 제외한다
가 되어 있기 때문에 「상품명이 명사 한 문자를 연결한 조어」인 경우, 검색에 걸리지 않게 되는 문제가 발생했습니다. 즉 폐사에서 제공하고 있는 「요락」이라고 하는 상품이 걸리지 않게 되었기 때문에 이하와 같이 수정해 운용하고 있습니다.

/**
 * 形態素解析による抜き出し
 *
 */
function MorphologicalAnalysis($txt){
    // 半角英数字のみの場合はそのまま
    if(preg_match("/^[!-~]+$/", $txt)){
        return $txt;
    }
    $mecab = new MeCab_Tagger();
    $meisi = array();
    $word = '';
    for($node=$mecab->parseToNode($txt); $node; $node=$node->getNext())
    {
        //if( $node->getStat() != 2 && $node->getStat() != 3 && mb_strpos($node->getFeature(), '名詞', NULL, 'utf-8')===0)
        {
            $word = $node->getSurface();
            //if (mb_strlen($word)>1)
            array_push($meisi, $word);          }
     }
    }
    return implode(" ", $meisi);
}

좋은 웹페이지 즐겨찾기