2016-02-15 4 views
9

Я пытаюсь сделать это на Ruby On Rails с Postgres PostGIS.как заказать и сгруппировать по подсчету подзапроса из упорядоченного списка по рубину на рельсах

Я пытаюсь сделать группировку и рассчитывать на город упорядоченного списка, который у меня есть.

У меня есть упорядоченный список ближайших точек к моим координатам (110.1862202 1.6031959).

Теперь я хочу сгруппировать по городам и подсчитать количество предметов в каждом городе. Однако формат верен, но каким-то образом он потерял свой заказ. Я бы хотел, чтобы города были заказаны ближе к моей координате. Все дело в том, чтобы добраться до ближайшего города, но теперь его не заказали ближе.

проблема запроса группы и сосчитать подзапрос

scope :nearestcitysubquery, ->() { 
    from(Treasure.order("ST_Distance(treasures.location_point, 
     ST_GeographyFromText('SRID=4326;POINT(110.1862202 1.6031959)'))"), 
     "subquery_treasure_nearest").group("city").count 
    } 

фактический результат

=> {"Kuala Lumpur"=>1, "null"=>1, "Sungai Besar"=>1, "Sungai Udang"=>1, "Kuching"=>1} 

ожидаемый результат

=> {"Kuching"=>1, "Sungai Besar"=>1, "Sungai Udang"=>1, "Kuala Lumpur"=>1, "null"=>1} 

Мой заказ запрос работает правильно

Treasure.order("ST_Distance(treasures.location_point, 
     ST_GeographyFromText('SRID=4326;POINT(110.1862202 1.6031959)'))") 

результат упорядочения (который правильно)

=> #<ActiveRecord::Relation [#<Treasure id: 5, user_id: 1, treasure_name: "Kucing", treasure_image: nil, description: "Kucing", hint: nil, location: "Jalan Ke Puncak Serapi", created_at: "2016-01-08 03:46:40", updated_at: "2016-01-08 03:46:40", treasure_id: "TRKKY", location_point: #<RGeo::Geographic::SphericalPointImpl:0x3fe9942b71c8 "POINT (110.18 1.6)">, city: "Kuching", state: "Sarawak", country: "Malaysia", difficulty: 2, google_place_id: "ChIJZf_iRaYF-zERMH5qt30cJJw", size: 2>, #<Treasure id: 4, user_id: 1, treasure_name: "Lori", treasure_image: nil, description: "Lori", hint: nil, location: "Jalan Samsudin", created_at: "2016-01-08 03:45:26", updated_at: "2016-01-08 03:45:26", treasure_id: "T3UKD", location_point: #<RGeo::Geographic::SphericalPointImpl:0x3fe9942bbd68 "POINT (102.14 2.27)">, city: "Sungai Udang", state: "Melaka", country: "Malaysia", difficulty: 2, google_place_id: "ChIJq6_zCZX50TERBdlr6V1CMDg", size: 2>, #<Treasure id: 3, user_id: 1, treasure_name: "Kapal", treasure_image: nil, description: "Kapal", hint: nil, location: "Unnamed Road", created_at: "2016-01-07 09:21:07", updated_at: "2016-01-07 09:21:07", treasure_id: "T3XQR", location_point: #<RGeo::Geographic::SphericalPointImpl:0x3fe9942ba29c "POINT (101.76 3.5)">, city: "null", state: "Selangor", country: "Malaysia", difficulty: 2, google_place_id: "ChIJWU_xuCoTzDERsigXByaXof4", size: 3>, #<Treasure id: 1, user_id: 1, treasure_name: "Kelapa", treasure_image: nil, description: "Food", hint: nil, location: "Jalan Kiara 3", created_at: "2016-01-07 06:08:56", updated_at: "2016-01-07 06:08:56", treasure_id: "TJKQL", location_point: #<RGeo::Geographic::SphericalPointImpl:0x3fe9943647d8 "POINT (101.65 3.17)">, city: "Kuala Lumpur", state: "Wilayah Persekutuan Kuala Lumpur", country: "Malaysia", difficulty: 2, google_place_id: "ChIJ8fBgm-1IzDERPHAF2dYtWTc", size: 2>, #<Treasure id: 2, user_id: 1, treasure_name: "Pulau", treasure_image: nil, description: "Pulau", hint: nil, location: "Jalan Parit 4 Barat", created_at: "2016-01-07 09:20:47", updated_at: "2016-01-07 09:20:47", treasure_id: "TO1BR", location_point: #<RGeo::Geographic::SphericalPointImpl:0x3fe9942bd744 "POINT (101.0 3.7)">, city: "Sungai Besar", state: "Selangor", country: "Malaysia", difficulty: 2, google_place_id: "ChIJAfwEx2lgyzERU_zVy8TqaW0", size: 3>]> 

ПРИМЕЧАНИЕ: Мне сказали, что подзапрос не для того, вероятно, внешнее соединение может работать. Как создать такой запрос?

ответ

3

В действительности существует несколько вещей, которые мешают вашему заказу работать.

  • Во-первых, как вы упомянули, любой ORDER пункт в подзапроса - который является тем, что ваш запрос расположение в - будет иметь никакого значения для того конечного набора результатов.

  • Во-вторых, ваш оговорка GROUP BY city делает логически невозможным упорядочить ваши результаты однозначно. Предположим, у вас есть сокровище A в городе X, расстояние = 10, сокровище B в городе Y, расстояние = 15, и сокровище C в городе X, расстояние = 20. Будет ли City X первым или последним в ваших результатах?

    Однако я думаю, что разумно предположить, что все города будут содержать сокровища примерно в аналогичной области, поэтому разумно заказать ближайший сокровищ. Поэтому мы можем справиться с этой проблемой.

  • Наконец, Rails 'group().count в настоящее время выводит хэш значений в значения. Этот API, вероятно, довольно новый и, вероятно, изменится (хеши действительно не следует заказывать, на мой взгляд, и формат не очень расширяемый). Поэтому полагаться на это может быть плохой идеей. Но, из моего тестирования, он делает выплевывает результаты в запрошенном порядке.

Короче говоря, то, что нам нужно сделать, это переместить order к верхнего уровня вашего запроса.Чтобы сделать это, пункт заказ необходимо использовать агрегатную функцию (я заеду МИН, чтобы заказать в ближайшем сокровище), и мы можем отбросить фантазии .from кода:

# I'm assuming this is on the Treasure model 
scope :nearestcitysubquery, ->() { 
    group('city') 
    .order("MIN(ST_Distance(treasures.location_point, 
     ST_GeographyFromText('SRID=4326;POINT(110.1862202 1.6031959)')))") 
    .count 
} 
+0

благодаря Роберт Nubel, будет проверять вас техника. кстати, где я могу положить .limit() для ограничения количества ближайших элементов (например, всего 30). Благодарю. – Axil

+0

Прежде чем '.count' должен это сделать (т. Е.' Group (...). Order (...). Limit (30) .count'). Дайте мне знать, если он не работает, как вы ожидаете. –

+0

Привет @Robert Nubel, предел неверен. Он ограничивает число городов (в этом примере 30 городов). Можем ли мы ограничить количество отсчетов? – Axil