ユーザーが検索を実行したときにキーワードが含まれている単語を検索したいと思います。 hook_query_alter()
にフックしようとしました:
_function MYMODULE_query_alter(&$query) {
// Check if this is a search query
if (!$query->hasTag('search_node')) {
return;
}
$conditions = &$query->conditions();
$conditions = &$conditions[1]['field']->conditions();
// Change the condition to '%<keyword>%'
// and add LIKE as operator
$conditions[0]['value'] = "%" . $conditions[0]['value'] . "%";
$conditions[0]['operator'] = 'LIKE';
}
_
検索クエリを変更できますが、結果が得られません。
実行される変更されたクエリは次のようになります。
_SELECT FROM {search_index} i
INNER JOIN {node} n ON n.nid = i.sid
INNER JOIN {search_total} t ON i.Word = t.Word
WHERE (n.status = :db_condition_placeholder_0)
AND ((i.Word LIKE :db_condition_placeholder_1 ESCAPE '\\'))
AND (i.type = :db_condition_placeholder_2)
GROUP BY i.type, i.sid
HAVING (COUNT(*) >= :matches)
_
また、SelectQuery
オブジェクトのプレースホルダーは次のように設定されています。
_[:db_condition_placeholder_0] => 1
[:db_condition_placeholder_1] => %liv%
[:db_condition_placeholder_2] => node
_
テーブル_search_index
_と_search_total
_の両方にliv
を含む2、3の単語が含まれていることを確認できるため、結果が返されるはずです。
ファジー検索 モジュールも試しましたが、提供された検索を通常の検索フォームに接続する方法がわかりません。
db_like()
を試しましたが、成功していません。
_=
_条件ではなくLIKE
を使用してインデックスを検索するようにデフォルトの検索を変更することがそれほど難しいのはなぜですか?
私がそれを実装する方法を知っているだけなら、このようなものはうまくいくはずです:
_$keyword = $_GET['s'];
$status = 1;
$types = array('article', 'contact');
db_query("SELECT node.nid FROM {node} n
INNER JOIN {search_index} si
ON si.sid = n.nid
AND si.Word LIKE :keyword
INNER JOIN {search_dataset} sd ON sd.sid = n.nid
WHERE n.status = :status AND n.type IN (:types)
GROUP BY n.nid", array(
':keyword' => '%' . db_like($keyword) . '%',
':status' => $status,
':types' => $types
)
);
_
SearchQuery::parseSearchExpression()
がそれを実行するため、変更したクエリでは結果が得られません。具体的には、300行目あたり:
// Single ANDed term.
else {
...
$this->conditions->condition('d.data', "% $key %", 'LIKE');
...
}
条件のスペースに注意してください。
結果を取得するには、これらのスペースをクエリから削除する必要がありますが、これは簡単な作業ではありません。私はこのようなものが必要になると信じています:
function my_module_query_alter($query) {
if ($query->hasTag('search_node')) {
$conditions = &$query->conditions();
$conditions = &$conditions[1]['field']->conditions();
$conditions[0]['value'] = '%' . $conditions[0]['value'] . '%';
$conditions[0]['operator'] = 'LIKE';
}
if ($query instanceof PagerDefault) {
PagerDefaultHelper::alter($query);
}
}
class PagerDefaultHelper extends PagerDefault {
public static function alter(PagerDefault &$query) {
$search_query = &$query->query;
SearchQueryHelper::alter($search_query);
}
}
class SearchQueryHelper extends SearchQuery {
public static function alter(SearchQuery &$query) {
$conditions = &$query->conditions->conditions();
$conditions[0]['value'] = str_replace(' ', '', $conditions[0]['value']);
}
}
ただし、これは単一の単語を検索する場合にのみ機能します。複数の単語、ORされた単語、または除外された単語を使用する検索では、このアプローチを構築する必要があります。
search api pages モジュール(またはビュー)を介してファジー検索を接続します。
ビューを使用する場合は、ビューの検索ブロックを目的の領域に配置できます。
手動による説明:(あいまい検索から)
db_like を使用してdb_like($ prefix)を追加すると、うまくいくと思います!
(i.Word LIKE :db_condition_placeholder_1 ESCAPE '\\')
Convert into:
condition('i.Word', db_like($prefix) . '%', 'LIKE')
私はカスタマイズの専門家ではありませんが、あなたに役立つかもしれません!
これがこの問題を解決する最良の方法であるかどうかはわかりませんが、結局 hook_node_update_index()
を使用して、単語の一部の検索をサポートしました。
function hook_node_update_index($node)
{
$result = '';
// how long should each part be?
$options = array(3, 4, 5);
// only look at the body and title
$content = $node->body['und'][0]['value'] . ' ' . $node->title;
$content = strip_tags($content);
$content = drupal_strtolower($content);
$words = explode(' ', $content);
$parts = array();
// split words into parts
foreach ($words as $Word) {
// if the length is less than the size we would like to split at
// then there's no need to continue
$length = drupal_strlen($Word);
foreach ($options as $option) {
if ($length < $option) {
$result .= ' ' . $Word;
break;
}
for ($i=0; $i < ($length - $option + 1); $i++) {
$parts[] = drupal_substr($Word, $i, $option);
}
}
}
// append all created parts for the words
if(count($parts)) {
$result .= ' ' . implode(' ', $parts);
}
return $result;
}
ドキュメントから:
関数hook_node_update_index
検索用にインデックス付けされているノードを操作します。
このフックは、node_load()の後、およびnode_view()の結果が$ node-> renderedとしてノードオブジェクトに追加された後に、検索インデックスの作成中に呼び出されます。
これは将来の誰かを助けるかもしれないので、私はこれを答えとして追加します。各キーワードにLIKE
条件を使用するより良いソリューションを探しています。