2009-06-14 43 views
7

Tôi là người mới bắt đầu với ORM của DataMapper, vì vậy tôi có câu hỏi về truy vấn phức tạp.Liên kết truy vấn DataMapper phức tạp

Thứ nhất, đây được đơn giản hóa đối tượng dữ liệu:

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 

Đây là cách dữ liệu trong db trông giống như:

+ ------- + + ------- + + ------- + 
| 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 | 
         | ....... | 
         + ------- + 

Vì vậy, ví dụ tài khoản 1 đã xem một số mặt hàng N lần. Và những gì tôi không thể tìm ra, làm thế nào để chọn các mục và số tiền hành động của họ liên quan đến người dùng.

Ví dụ, kết quả cho người sử dụng 1 nên được như thế này:

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

T.B. truy vấn SQL thông thường phù hợp với nhu cầu của tôi:

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; 

Vì vậy, cách thực hiện điều này và có bất kỳ tài liệu nào về truy vấn datamapper phức tạp không?

Trả lời

2

Theo như tôi biết, không có nhóm nào theo toán tử trong bộ dữ liệu hoặc bất kỳ plugin nào của nó. Nếu có, nó sẽ đi trong dm-aggregates cùng với các hàm tổng hợp (đếm, min, max, avg). Điều đó làm cho nó khó khăn để tái tạo những gì bạn muốn trong một truy vấn mà không sử dụng sql.

Bạn có thể thử một cái gì đó như thế này:

require 'dm-aggregates' 

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

Tuy nhiên, bạn có thể chỉ là một cách dễ dàng mất sql của bạn và bọc nó trong một 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 trả về một mảng của cấu trúc, do đó bạn có thể làm những việc như

user.item_views[0].title 
12

Trong trường hợp ai vẫn đang tự hỏi:

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

Sẽ trở lại một cái gì đó giống như

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

Không có cách nào để đặt hàng bởi all.count ở đây, nhưng nó sẽ cho bạn dữ liệu bạn muốn :)

+0

Cảm ơn - nó không hề rõ ràng từ tài liệu của DataMapper. DM tạo mã SQL chặt chẽ hơn AR, nhưng phải có câu trả lời StackOverflow như thế này để tìm hiểu cách thực hiện. –

Các vấn đề liên quan