简体   繁体   中英

intersection and pagination in Eloquent ORM

Hi everybody I have 3 table:

a table called content with the below attributes:

id
name
table_type_id
release_date
popularity

another table called content_genres with the below attributes:

content_id
genres_id

another table called genres with the below attributes:

id
name

each content can have multiple genres, and a genre can have multiple content.( many to many )


okay, until here is the definition of the different tables, now i am trying to make a query to search the content that has for example the genre_id=1 and at the same time the genre_id=2

in postgresql this would be easy:

 SELECT content.id
 FROM content INNER JOIN content_genres ON content.id =content_genres.content_id
 WHERE content_genres.`genres_id`= 1

 INTERSECT

 SELECT content.id
 FROM content INNER JOIN content_genres ON content.id =content_genres.content_id
 WHERE content_genres.`genres_id`= 2
 ;

I make one query, I make another query and then I make an intersection getting that content that has the genre_id 1 and 2


but when I try to write this same query in eloquent I have some problems:

query 1:

$content1=$this->content::join('content_genres','content_genres.content_id','=','content.id')
        ->with('genres')
        ->where('content_genres.genres_id',1)
        ->where('content.table_type_id',1)
        //->whereYear('release_date',2017)
        ->select('content.id','content.name','content.popularity')
        ->orderBy('popularity','desc')->get();

query 2:

$content2=$this->content::join('content_genres','content_genres.content_id','=','content.id')
        ->with('genres')
        ->where('content_genres.genres_id',2)
        ->where('content.table_type_id',1)
        //->whereYear('release_date',2017)
        ->select('content.id','content.name','content.popularity')
        ->orderBy('popularity','desc')->get();

intersection:

 $final_result=$content1->intersect($content2);

okay how we have seen at this way we are able to make a intersection but I have some problems:

when I want to do a manual pagination I don't know how can I count the elements that is going to have the intersection, and after that limit the results of the intersection.

example:

number of results from query1:

18950

number of results from query2:

22650

number of results from intersection

3457

this is very slow, because I can not say limit the query 1 to 100 results, limit the query 2 to 100 results and then make the intersection, I can not do this because the number of results from the intersection is not going to be always the same so for that reason how can I make a manual pagination over the intersection without load all the results from query1 and query2, saying I want to paginate the intersections in pages from 20 results?

The last thing is the big problem which I have had all the week.


real example

you go to this page, then in year put none, and in genres select two random genres. how you can see the pagination of that intersection is always 20, doesn't depends if there is more results in the intersection or there isn't, always is 20. And I am pretty sure that they haven't load from the db all the results.


Good result:

Thanks to the answer the correct way to do this is the below:

 $this->content::join('content_genres as g1','g1.content_id','=','content.id')
->join('content_genres as g2','g2.content_id','=','content.id')
->where('g1.genres_id', 1)
->where('g2.genres_id', 2)

it works for me, I could have chosen the other option but I have a many to many relation , because my content_genres is a pivot table, but I think that I would be also valid.

You should merge both queries. I see two ways of doing this.

1) Join content_genres twice:

$this->content::join('content_genres as g1','g1.content_id','=','content.id')
    ->join('content_genres as g2','g2.content_id','=','content.id')
    ->where('g1.genres_id', 1)
    ->where('g2.genres_id', 2)

2) Use whereHas() :

$this->content::whereHas('content_genres', function($query) {
    $query->where('genres_id', 1)
})->whereHas('content_genres', function($query) {
    $query->where('genres_id', 2)
})

This requires a relationship: content → HasMany → content_genres

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM