代码之家  ›  专栏  ›  技术社区  ›  Dan Sosedoff

复杂数据映射器查询关联

  •  7
  • Dan Sosedoff  · 技术社区  · 15 年前

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

    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
    

    数据库中的数据是这样的:

    + ------- + + ------- + + ------- +
    | 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的结果应如下所示:

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

    P.S.符合我需要的常规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;
    

    那么,如何做到这一点,是否有关于复杂datamapper查询的文档?

    2 回复  |  直到 12 年前
        1
  •  12
  •   mltsy    14 年前

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

    将返回类似于

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

    这里没有按all.count排序的方法,但它可以获得所需的数据:)

        2
  •  2
  •   BaroqueBobcat    15 年前

    据我所知,datamapper或其任何插件中都没有GroupBy操作符。如果有,它将与聚合函数(count、min、max、avg)一起放入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