EC-CUBE 검색에 형태소 해석 엔진 (MeCab)을 구현하는 샘플
형태소 분석
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);
}
Reference
이 문제에 관하여(EC-CUBE 검색에 형태소 해석 엔진 (MeCab)을 구현하는 샘플), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/keitone/items/1081d0d497f80a83e121
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
예를 들면 「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);
}
Reference
이 문제에 관하여(EC-CUBE 검색에 형태소 해석 엔진 (MeCab)을 구현하는 샘플), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/keitone/items/1081d0d497f80a83e121
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
여기 의 거리입니다.
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);
}
Reference
이 문제에 관하여(EC-CUBE 검색에 형태소 해석 엔진 (MeCab)을 구현하는 샘플), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/keitone/items/1081d0d497f80a83e121
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
/**
* 検索条件の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);
}
Reference
이 문제에 관하여(EC-CUBE 검색에 형태소 해석 엔진 (MeCab)을 구현하는 샘플), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/keitone/items/1081d0d497f80a83e121
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
/**
* 形態素解析による抜き出し
*
*/
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);
}
Reference
이 문제에 관하여(EC-CUBE 검색에 형태소 해석 엔진 (MeCab)을 구현하는 샘플), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/keitone/items/1081d0d497f80a83e121텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)