Сложная ассоциация запросов DataMapper - PullRequest
7 голосов
/ 15 июня 2009

Я новичок в 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

Вот так выглядят данные в БД:

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

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 голосов
/ 13 декабря 2010

На случай, если кому-то все еще интересно:

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

Вернет что-то вроде

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

Нет способа сделать заказ по all.count здесь, но он даст вам нужные данные:)

2 голосов
/ 12 августа 2009

Насколько я знаю, в datamapper нет ни одной группы по операторам или ее плагинов. Если бы это было так, оно бы входило в dm-агрегаты вместе с функциями агрегирования (count, min, max, avg) Это затрудняет репликацию того, что вы хотите в одном запросе, без использования sql.

Вы можете попробовать что-то вроде этого:

require 'dm-aggregates'

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

Но вы также можете легко взять свой sql и обернуть его в фн.

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...