7

我是 DataMapper ORM 的初学者,所以我对复杂查询有疑问。

首先,这里是简化的数据对象:

class User  
    property :id, Serial
    property :login, String

    has n, :actions
end

class Item
    property :id, Serial
    property :title

    has n, :actions
  has n, :users, :through => :actions
end

class Action
    property :user_id, Integer
    property :item_id, Integer

    belongs_to :item
    belongs_to :user
end

这是 db 中的数据的样子:

+ ------- + + ------- + + ------- +
| Users   | | Items   | | Actions |
+ ------- + + ------- + + ------- +
| 1  | u1 | | 3  | i1 | | 1  | 4  |
| 2  | u2 | | 4  | i2 | | 1  | 3  |
| ....... | | 5  | i3 | | 1  | 4  |
+ ------- + | ....... | | 1  | 5  |
            + ------- + | 1  | 6  |
                        | 1  | 3  |
                        | ....... |
                        + ------- +

因此,例如,用户 1 已经查看了一些项目 N 次。我想不通的是,如何选择项目及其与用户相关的操作量。

例如,用户 1 的结果应该是这样的:

+ -------------------- |
| Items (item_id, num) |
+ -------------------- |
| 3, 2                 |
| 4, 2                 |
| 5, 1                 |
| 6, 1                 |
+ -------------------- +

符合我需要的 PS 常规 SQL 查询:

SELECT i.id, i.title, COUNT(*) as 'num'
FROM actions a
JOIN items i on i.id = a.item_id
WHERE a.user_id = {USERID}
GROUP by a.id
ORDER BY num DESC
LIMIT 10;

那么,如何做到这一点,是否有任何关于复杂数据映射器查询的文档?

4

2 回答 2

12

如果有人仍然想知道:

Action.aggregate(:item_id, :all.count, :user_id => 1, :order => [item_id.asc])

会返回类似的东西

[ [ 3, 2 ],
  [ 4, 2 ],
  [ 5, 1 ],
  [ 6, 1 ]
]

无法在这里按 all.count 订购,但它可以为您提供所需的数据 :)

于 2010-12-13T19:26:06.893 回答
2

据我所知,datamapper 或其任何插件中都没有 group by 运算符。如果有,它将与聚合函数(计数、最小值、最大值、平均值)一起进入 dm 聚合。这使得在不使用 sql 的情况下很难在一个查询中复制您想要的内容。

你可以尝试这样的事情:

require 'dm-aggregates'

Item.all.map do |item|
  [item.title,item.actions.count(:user_id=>@user_id)]
end

但是,您可以轻松地获取您的 sql 并将其包装在 fn 中。

class User
  def item_views
  repository.adapter.query "SELECT i.id, i.title, COUNT(*) as 'num'
    FROM actions a
    JOIN items i on i.id = a.item_id
    WHERE a.user_id = {USERID}
    GROUP by a.id
    ORDER BY num DESC
    LIMIT 10;"
  end
end

repository.adapter.query返回一个结构数组,因此您可以执行以下操作

user.item_views[0].title
于 2009-08-11T20:07:54.473 回答