2012-03-09 16 views
2

2つのモデルが関連付けられています。私はArtistモデルとReviewモデルを持っています。datamapperを使用して結果の順序を指定する

class Artist 
    include DataMapper::Resource 

    property :id, Serial 
    property :name, String 

    has n, :reviews 

end 

class Review 
    include DataMapper::Resource 

    property :id, Serial 
    property :rating, Integer 
    property :body, String 

    belongs_to :artist 
end 

私の目標は、それらに関連レビューの平均評価順アーティストの配列を取得することです。私はこれに1行の解決策があるかどうかはわかりませんが、私の現在の方法はアーティストのIDが平均格付けでソートされた配列を作成することです。この配列を取得する方法の詳細はこの質問では重要ではありませんが、今は配列があるとしましょう。

ids_sorted_by_rating = [4,5,23,9,2,48,17,....] 

次にアーティストを取得します。

artists = Artist.all(:id => ids_sorted_by_rating) 

問題は、別のオプションを指定しない限り、datamapperはid by ordersです。ですから、ids_sorted_by_ratingを取得するのが大変な作業の後、私はまだidによってソートされたアーティストのリストが残っています。

関連するレビューの平均評価によって注文されたアーティストのリストを私に提供するすべての解決策は非常に高く評価されます。ボーナスポイントは、そのリストを取得するのに何百万回もデータベースをヒットする必要がない場合です。 :)

おかげさまで、さらに詳しい情報が必要な場合は、私が提供します。

答えて

1

AFAIK DataMapperでの集計による並べ替えを簡単に行う方法はありません(単一クエリで行う方法)。あなただけ(例えば、あなたがリストでWebページを作成している)のデータを表示したい場合は

hash = artists.index_by(&:id) 
# if you do not have index_by - use a artists.inject({}){|h,a| h.merge(a.id => a)} 
ids_sorted_by_rating.map{|id| hash[id]} 
+0

私はあなたを忘れていませんでした。私はこれを試してみる機会がありませんでした。 – wuliwong

+0

ありがとう、私は解決するためにこの質問を書いていた問題とは別の方向に巻き上げましたが、私は新しい場所でこの同じ問題を思いつきました。私はこれを行うには、datamapper ':through => Resource'と言うのではなく、カスタムアソシエーションを作成する必要があると思います。 – wuliwong

0

と:あなたは(あなたのデータセットが、このために大きすぎる場合を除き)結果のアプリ側の並べ替えを使用することができますArtistsあなたは(あなたがSQLデータストアを使用していると仮定して)「カンニング」とSQLを使用することができますを変更するつもりはありません。

repository(:default).adapter.select(
'SELECT artists.* 
FROM artists JOIN reviews on artists.id = reviews.artist_id 
GROUP BY artists.id 
ORDER BY AVG(reviews.rating)') 

これはArtistオブジェクトを返しませんが、Structsの配列が、その意志それぞれがArtistのすべてのプロパティを持っているので、すべてのデータを取得できますが、更新するとあまりうまく行かないでしょう。その後のクエリで「実際の」Artistを取得できます(たとえば、ユーザーがアーティストのリンクをクリックし、適切なid値を使用して対応するArtistオブジェクトを照会できます)。

また、SQLのさまざまな方言に注意する必要がありますし、使用しているDBMSで動作するように調整する必要があるかもしれません(これはSqliteで動作します。

しかし、配列は各アーティストのレビューの平均評価順に並べられます。

+0

私はこのパスをとることを考えましたが、ローカルマシンかherokuに依存してSqliteとPostgresを切り替えます。まっすぐなDatamapperを使うだけでいいし、SqliteからPostgresへの変更を1行に記述することができます。しかし、ありがとう。将来的にリソース消費の重大な問題になる場合、私はこのようなものを実装しなければならないかもしれません。 – wuliwong

関連する問題