问题
I have a large relationship models between many entities.
Menu <> MenuSection <> Section <> SectionEntry <> Entry
Entry <> EntryTag <> Tag
Menu <> MenuLocation <> Location
The Location entity got attributes like longitude and latitude to calculate the distance between the user's current position and the "location".
I wrote a lil' bit larger doctrine query. YES, there are many relationships (many to many, many to one and so on, but the relation tables (e.g. entry_section) exist to store some more data on it). Let me show you my query.
$d = $this->getDoctrine()->getRepository('AppBundle:Entry')->createQueryBuilder('entry')
->select('entry')
->innerJoin('AppBundle:SectionEntry', 'section_entry', 'WITH', 'section_entry.entry_id = entry.id')
->innerJoin('AppBundle:Section', 'section', 'WITH', 'section.id = section_entry.section_id')
->innerJoin('AppBundle:MenuSection', 'menu_section', 'WITH', 'menu_section.section_id = section.id')
->innerJoin('AppBundle:Menu', 'menu', 'WITH', 'menu.id = menu_section.menu_id')
->innerJoin('AppBundle:MenuLocation', 'menu_location', 'WITH', 'menu_location.menu_id = menu.id')
->innerJoin('AppBundle:Location', 'location', 'WITH', 'location.id = menu_location.location_id');
if (!empty($tags)) {
$d->innerJoin('AppBundle:EntryTag', 'entry_tag', 'WITH', 'entry.id = entry_tag.entry_id')
->where('entry_tag.tag_id IN (' . implode(',', $tags) . ')');
}
$d->addSelect(
'( 6371 * acos(cos(radians(' . $lat . '))' .
'* cos( radians( location.latitude ) )' .
'* cos( radians( location.longitude )' .
'- radians(' . $long . ') )' .
'+ sin( radians(' . $lat . ') )' .
'* sin( radians( location.latitude ) ) ) ) as distance'
);
if ($dist != 0) {
$d->andHaving('distance < :distance')
->setParameter('distance', $dist);
}
$d->addOrderBy('distance', 'ASC')
->addOrderBy('location.id', 'ASC')
->setFirstResult(0)
->setMaxResults(20);
$entries = $d->getQuery()->getResult();
foreach ($entries as $no => $entry) {
echo '[' . ($no+1) . ']' . $entry[0]->getId() . ': ' . $entry[0]->getSectionEntry()->first()->getSection()->getMenuSection()->first()->getMenu()->getMenuLocations()->first()->getLocation()->getAddress() . ' (' . $entry['distance'] . ')<br />'; // debug
}
// $entry[0]->getSectionEntry()->first()->getSection()->getMenuSection()->first()->getMenu()->getMenuLocations()->first()->getLocation()->getAddress() is very long :-) debug reason
die();
There is a problem in the result. No error, but the result is a lil' bit confusing. I try to get Entries, inner join tables to reach the "location" class related to it, to calculate the distance at once. And i want to limit the result (entries) with ->setMaxResults(20), e.g. 20. All fine. But: It get less Entries than 20. There are 100, 200 or so within database. But it will deliver me 11 or 12 or something.
I don't know what is happening here. I think doctrine makes multiple sql queries in the background. He needs ~3 queries to get one entry for the result. So if i write: setMaxResults(3) i will get 1 entry. 6 will get 2 entries and so on. Its just a suspicion. I don't know. Thats why i am asking for your help :)
I tried to add ->addGroupBy('entry.id') ... Then i get the right number of result! setMaxResult(10) delivers 10 results then but then the distance is weird.
Let me give you an example. When i use ->addGroupBy('entry.id') and ->setMaxResult(30) then doctrine delivers 30 Entries and the distance for it! But some result items are not correct (distance is wrong). Let me show you. E.g, result:
0, Entry, location_id 1, distance=1,8
1, Entry, location_id 1, distance=1,8
2, Entry, location_id 1, distance=1,8
3, Entry, location_id 1, distance=1,8
4, Entry, location_id 1, distance=1,8
5, Entry, location_id 1, distance=1,8
6, Entry, location_id 1, distance=1,8
7, Entry, location_id 1, distance=1,8
8, Entry, location_id 1, distance=1,8
9, Entry, location_id 1, distance=1,8
10, Entry, location_id 1, distance=1,8
11, Entry, location_id 1, distance=1,8
12, Entry, location_id 1, distance=1,8
13, Entry, location_id 1, distance=1,8
14, Entry, location_id 1, distance=1,8
15, Entry, location_id 2, distance=1,8
16, Entry, location_id 2, distance=1,8
17, Entry, location_id 2, distance=1,8
18, Entry, location_id 2, distance=1,8
19, Entry, location_id 2, distance=1,8
20, Entry, location_id 2, distance=4,5
21, Entry, location_id 2, distance=4,5
22, Entry, location_id 2, distance=4,5
23, Entry, location_id 2, distance=4,5
24, Entry, location_id 2, distance=4,5
25, Entry, location_id 2, distance=4,5
26, Entry, location_id 2, distance=4,5
27, Entry, location_id 2, distance=4,5
28, Entry, location_id 2, distance=4,5
29, Entry, location_id 2, distance=4,5
30, Entry, location_id 2, distance=4,5
1,8 and 4,5 are correct! but your can see, the distance is wrong for these result items:
15, Entry, location_id 2, distance=1,8
16, Entry, location_id 2, distance=1,8
17, Entry, location_id 2, distance=1,8
18, Entry, location_id 2, distance=1,8
19, Entry, location_id 2, distance=1,8
location_id is another location but 15, 16, 17, 18 and 19 got the same distance as the location_id 1 have.
So this is mixed weird. But why? I think i got some problem writing the doctrine query in a correct way.
Can you help me fixing this?
来源:https://stackoverflow.com/questions/36919595/symfony2-and-doctrine-query-with-distance-lonigtude-and-latitude-and-large-rel