首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >更改Drupal 7中数据集的搜索查询条件

更改Drupal 7中数据集的搜索查询条件
EN

Stack Overflow用户
提问于 2014-09-12 13:20:01
回答 2查看 2.2K关注 0票数 1

我对Drupal非常陌生,并试图构建一个模块,允许管理员用关键字标记节点,从而将节点提升到搜索结果的顶部。

对于关键字和相应的节点ID,我有一个单独的DB表。这个表是UNIONed,search_index表通过更改.

代码语言:javascript
复制
function mos_search_result_forcer_query_alter(QueryAlterableInterface &$query) {
    if (get_class($query) !== 'PagerDefault') { //<< check this because this function will mod all queries elsewise
        return;
    }

    // create unioned search index result set...
    $index = db_select('search_index', 's');

    $index->addField('s', 'sid');
    $index->addField('s', 'word');
    $index->addField('s', 'score');
    $index->addField('s', 'type');

    $msrfi = db_select('mos_search_result_forcer', 'm');

    $msrfi->addField('m', 'nid', 'sid');
    $msrfi->addField('m', 'keyword', 'word');
    $msrfi->addExpression('(SELECT MAX(score) + m.id / (SELECT MAX(id) FROM {mos_search_result_forcer}) FROM {search_index})', 'score');
    $msrfi->addExpression(':type', 'type', array(':type' => 'node'));

    $index->union($msrfi);

    $tables =& $query->getTables();

    $tables['i']['table'] = $index;

    return $query;
}

然后Drupal生成几乎正确的查询..。

代码语言:javascript
复制
SELECT 
    i.type AS type, i.sid AS sid, SUM(CAST('10' AS DECIMAL) * COALESCE(( (12.048628015788 * i.score * t.count)), 0) / CAST('10' AS DECIMAL)) AS calculated_score 
FROM (
    SELECT 
        s.sid AS sid, s.word AS word, s.score AS score, s.type AS type 
    FROM 
        search_index s 
    UNION SELECT 
        m.nid AS sid, m.keyword AS word, (
            SELECT 
                MAX(score) + m.id / (SELECT MAX(id) FROM mos_search_result_forcer) 
            FROM 
                search_index
        ) AS score, 'node' AS type 
    FROM 
        mos_search_result_forcer m
) i 
INNER JOIN node n ON n.nid = i.sid 
INNER JOIN search_total t ON i.word = t.word 
INNER JOIN search_dataset d ON i.sid = d.sid AND i.type = d.type 
WHERE (n.status = '1') 
AND( (i.word = 'turtles') )
AND (i.type = 'node') 

/* this is the problem line... */
AND( (d.data LIKE '% turtles %' ESCAPE '\\') )
/* ...end problem line */

GROUP BY i.type, i.sid 
HAVING (COUNT(*) >= '1') 
ORDER BY calculated_score DESC 
LIMIT 10 OFFSET 0

...I需要那条“问题线”来读.

代码语言:javascript
复制
AND( (d.data LIKE '% turtles %' ESCAPE '\\') OR (d.sid IN (SELECT nid FROM mos_search_result_forcer)) )

...what钩子我可以用来添加那个或条件吗?

  • 我不想黑德鲁帕尔的核心。
  • 我不想改变联盟/子查询(不是我的决定)。
  • 稍后我将优化查询--功能更重要。

谢谢,聪明人!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-09-16 17:26:26

感谢@Clive with hook_module_implements_alter的一些有用的建议,以及大量的尝试和错误,我终于解决了这个问题。

这是最后的密码。

代码语言:javascript
复制
function mos_search_result_forcer_module_implements_alter(&$imps, $hook) {
    if ($hook !== 'query_alter' || !array_key_exists('mos_search_result_forcer', $imps)) {
        return;
    }

    $imp = $imps['mos_search_result_forcer'];

    unset($imps['mos_search_result_forcer']);

    $imps['mos_search_result_forcer'] = $imp;
}

function mos_search_result_forcer_query_alter(QueryAlterableInterface &$query) {
    if (get_class($query) !== 'PagerDefault') { //<< check this because this function will mod all queries elsewise
        return;
    }

    // create unioned search index result set...
    $index = db_select('search_index', 's');

    $index->addField('s', 'sid');
    $index->addField('s', 'word');
    $index->addField('s', 'score');
    $index->addField('s', 'type');

    $msrfi = db_select('mos_search_result_forcer', 'm');

    $msrfi->addField('m', 'nid', 'sid');
    $msrfi->addField('m', 'keyword', 'word');
    $msrfi->addExpression('(SELECT MAX(score) + m.id / (SELECT MAX(id) FROM {mos_search_result_forcer}) FROM {search_index})', 'score');
    $msrfi->addExpression(':type', 'type', array(':type' => 'node'));

    $index->union($msrfi);

    $tables =& $query->getTables();

    $tables['i']['table'] = $index;

    // needs special "or" condition to keep from filtering out forced resutls...
    class MSRFPagerDefaultHelper extends PagerDefault { //<< override to gain access to protected props
        static function msrfHelp(PagerDefault &$pagerDefault) {
            $searchQuery =& $pagerDefault->query;

            MSRFSearchQueryHelper::msrfHelp($searchQuery);
        }
    }

    class MSRFSearchQueryHelper extends SearchQuery { //<< override to gain access to protected props
        static function msrfHelp(SearchQuery &$searchQuery) {
            $conditions =& $searchQuery->conditions;

            $condition = db_or()->condition($conditions)->condition('d.sid', db_select('mos_search_result_forcer')->fields('mos_search_result_forcer', array('nid')), 'IN');

            $searchQuery->conditions = $condition;
        }
    }

    MSRFPagerDefaultHelper::msrfHelp($query);

    return $query; //<< i don't think this is needed as var is reffed - just for good measure, i guess
}
票数 0
EN

Stack Overflow用户

发布于 2014-09-13 12:48:07

其基本原理是获取条件数组,循环遍历并查找问题条件的索引,删除它,然后重新添加一个与新条件相同的条件,作为db_or()的一部分。

这是未经测试的,很可能无法逐字工作,但它应该给您一个起点:

代码语言:javascript
复制
$conditions =& $query->conditions();
$index = FALSE;
$removed_condition = NULL;

for ($i = 0, $l < count($conditions); $i < $l; $i++) {
  if ($conditions[$i]['field'] == 'd.data' && $conditions[$i]['operator'] == 'LIKE') {
    $index = $i;
    $removed_condition = $condition;

    break;
  }
}

if ($index !== FALSE) {
  unset($conditions[$index]);

  $sub_query = db_select('mos_search_result_forcer')->fields('mos_search_result_forcer', array('nid'));
  $new_condition = db_or()
    ->condition('d.data', $removed_condition['value'], 'LIKE')
    ->condition('d.sid', $sub_query, 'IN');

  $query->condition($new_condition);
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25809322

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档