2009-06-14 31 views
7

Soy un principiante con DataMapper ORM, así que tengo preguntas sobre consultas complejas.Asociación compleja de consulta de DataMapper

primer lugar, los objetos de datos que aquí se simplifica:

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 

Esta es la cantidad de datos en el PP parece:

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

Así, por ejemplo Usuario 1 ha visto algunos artículos N tiempo. Y lo que no puedo entender, cómo seleccionar elementos y su cantidad de acción relacionada con el usuario.

Por ejemplo, el resultado para el usuario 1 debe ser como este:

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

P.S. consulta regular de SQL que se ajuste a mis necesidades:

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; 

Entonces, ¿cómo hacer esto y es que hay alguna documentación acerca de las consultas complejas DataMapper?

Respuesta

2

Por lo que sé, no hay un operador por grupo en datamapper o cualquiera de sus complementos. Si lo hubiera, iría en dm-aggregates junto con las funciones de agregación (count, min, max, avg). Eso hace que sea difícil replicar lo que quiere en una consulta sin usar sql.

usted podría intentar algo como esto:

require 'dm-aggregates' 

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

Pero, usted podría fácilmente llevar a su SQL y se envuelve en una 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 devuelve una matriz de estructuras por lo que podría hacer cosas como

user.item_views[0].title 
12

En caso de que alguien todavía se pregunta:

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

¿Se volverá algo así como

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

No hay forma de ordenar por all.count aquí, pero obtiene los datos que desea :)

+0

Gracias - no está del todo claro en la documentación de DataMapper. DM produce un código SQL más ajustado que AR, pero necesita una respuesta de StackOverflow como esta para saber cómo hacerlo. –

Cuestiones relacionadas