我当前的表格配置如下
PagesTable
$this->belongsToMany('Keywords', ['through' => 'PagesKeywords']);
PagesKeywordsTable
架构: id,page_id,keyword_id,相关性
$this->belongsTo('Pages');
$this->belongsTo('Keywords');
KeywordsTable
$this->belongsToMany('Pages', ['through' => 'PagesKeywords']);
现在是我正在努力的事情......
通过关键字查找网页,使用精确的数组然后按 PagesKeywords.relevance
排序(这基本上是存储每页关键字重复的次数,因此连接表中没有重复的关键字)
我目前这个工作正常,除了它按关键字本身对关键字的结果进行分组,我需要将它们按Pages.id分组。
以下是我在Pages控制器中的搜索操作:
$keywords = explode(" ", $this->request->query['q']);
$query = $this->Pages->Keywords->find()
->where(['keyword IN' => $keywords])
->contain(['Pages' => [
'queryBuilder' => function ($q) {
return $q->order([
'PagesKeywords.relevance' =>'DESC'
])->group(['Pages.id']);
}
]]);
$pages = array();
foreach($query as $result) {
$pages[] = $result;
}
我知道这似乎是一种落后的做事方式,但它是我似乎能够通过_joinTable订购的唯一方式(PagesKeywords.relevance)
这会返回我需要的结果,但现在需要按Pages.id进行分组,这就是整个事情进入底池的地方..
要明确我想要的结构是:
Page data 1
Page data 2
Page data 3
Page data 4
目前正在返回的位置:
Keyword "google"
------- Page data 1
------- Page data 2
------- Page data 3
------- Page data 4
Keyword "something"
------- Page data 1
------- Page data 2
------- Page data 3
------- Page data 4
如果你能帮助我那么棒!
由于
答案 0 :(得分:0)
如果您在使用ORM进行复杂查询时遇到问题,我发现找出我需要的SQL所需的SQL总是更容易,然后将其调整到ORM。
您正在寻找的查询将是这样的(使用MySQL引擎...... MySQL Handles字段在GROUP BY子句中比其他SQL引擎更自由地选择)
SELECT Pages.*, COUNT(DISTINCT(PagesKeywords.keyword_id)) AS KeywordCount
FROM pages Pages
INNER JOIN pages_keywords PagesKeywords ON (PagesKeywords.page_id = Pages.id)
INNER JOIN keywords Keywords ON (Keywords.id = PagesKeywords.keyword_id)
WHERE Keywords.name IN ('keyword1','keyword2')
GROUP BY Pages.id
这将为您提供包含关键字的所有网页,KeywordCount将包含不同的附加关键字的数量。
所以这样的finder方法看起来像(在这里进行ad-hoc,所以我的语法可能会不稳定)
**在PagesTable模型中**
public function findPageKeywordRank(Query $q, array $options) {
$q->select(['Pages.*','KeywordCount'=>$q->func()->count('DISTINCT(PagesKeywords.keyword_id)'])
->join([
'PagesKeywords'=>[
'table'=>'pages_keywords',
'type'=>'inner',
'conditions'=>['PagesKeywords.page_id = Pages.id']
],
'Keywords'=>[
'table'=>'keywords',
'type'=>'inner',
'conditions'=>['Keywords.id = PagesKeywords.keyword_id']
]
])
->group(['Pages.id']);
return $q;
}
然后你可以查询所有查询器
$pages = TableRegistry::get("Pages")->find('PageKeywordRank')
->where(['Keywords.name'=>['keyword1','keyword2']]);