douling8772 2015-09-05 22:40
浏览 21
已采纳

CakePHP 3按关键字按页面分组查找

My current config of tables is as follows

PagesTable

$this->belongsToMany('Keywords', ['through' => 'PagesKeywords']);

PagesKeywordsTable

Schema: id, page_id, keyword_id, relevance

$this->belongsTo('Pages');
$this->belongsTo('Keywords');

KeywordsTable

$this->belongsToMany('Pages', ['through' => 'PagesKeywords']);

Now heres what i'm trying to do..

Find pages via keywords, using an array to be precise then order by PagesKeywords.relevance

(This is basically storing how many time that keyword is repeated per page, so no duplicate keywords in join table)

I've currently got this working fine except it groups the results of keywords by the keyword itself, where as I need them to be grouped by Pages.id

Here is what i have in my Pages controller, search action:

$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;

        }

I know this seems like a backward way to do things but its the only way I seemed to be able to order by _joinTable (PagesKeywords.relevance)

This returns the results I need but now it needs to be grouped by Pages.id which is where this whole thing goes to pot..

Just to be clear the structure I want is:

Page data 1
Page data 2
Page data 3
Page data 4

Where as its currently returning:

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

If you are able to help me thats great!

Thanks

  • 写回答

1条回答 默认 最新

  • dozrhldy285751 2015-09-06 03:23
    关注

    If you're having issues with complex queries with an ORM, I find it always easier to figure out the SQL I need to get the results I require, then adapt that to the ORM.

    The query you're looking for would be like this (Using MySQL engine... MySQL Handles field selects more liberally in GROUP BY clauses than other SQL engines )

    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
    

    This will give you all pages that contain the keyword and KeywordCount will contain the number of distinct attached Keyword.id's

    So a finder method for this would look like ( going ad-hoc here so my syntax might be shaky )

    ** Inside your PagesTable model **

    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;
    }
    

    Then you can all your finder query

    $pages = TableRegistry::get("Pages")->find('PageKeywordRank')
                                        ->where(['Keywords.name'=>['keyword1','keyword2']]);
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 想问一下树莓派接上显示屏后出现如图所示画面,是什么问题导致的
  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计
  • ¥15 cmd cl 0x000007b
  • ¥20 BAPI_PR_CHANGE how to add account assignment information for service line
  • ¥500 火焰左右视图、视差(基于双目相机)
  • ¥100 set_link_state
  • ¥15 虚幻5 UE美术毛发渲染
  • ¥15 CVRP 图论 物流运输优化
  • ¥15 Tableau online 嵌入ppt失败
  • ¥100 支付宝网页转账系统不识别账号