Mongoid: Как загружать только некоторые поля объекта, который вы ленивы загружаете через ссылку?

По соображениям производительности я использую как можно чаще ключевое слово only() при написании мангулярного запроса, чтобы указать поля, которые я хочу загрузить.

Обычный подозреваемый, например, когда я хочу, чтобы пользователь электронной почты всех моих администраторов был только для показа.

Я бы написал:

User.where(:groups => :admins).only(:email).each do |u|
 puts u.email
end

Я делаю это, потому что моя модель пользователя заполнена множеством данных, которые я с радостью могу игнорировать при перечислении писем.

Однако теперь представьте себе, что мои пользователи ссылаются через модель Project, так что для каждого проекта я могу сделать: project.user. Благодаря лёгкой загрузке mongoid пользователь моего объекта будет получать экземпляр (и запрашивается из БД), когда я вызываю ссылку.

Но что, если я хочу, например, перечислить все электронные письма владельца всего проекта администратора?

Я бы написал следующее:

Project.where(:admin_type => true).each do |p|
  puts p.user.email
end

Основная проблема заключается в том, что при этом я загружаю весь пользовательский объект для каждого проекта, и если есть много проектов, соответствующих запросу, которое может стать довольно тяжелым. Итак, как мне загружать только электронные письма?

Я мог бы сделать это:

User.where(:_id => p.user_id).only(:email).first.email

Но это явно побеждает цель простого синтаксиса просто:

p.user.email 

Мне хотелось бы написать что-то вроде: p.user.only(:email).email, но я не могу. Любые идеи?

Алекс

Ответ 1

Ответ от создателя Монгоида. Это пока невозможно. Он был добавлен как запрос функции.

Ответ 2

Думаю, вам нужно денормализовать здесь. Прежде всего, прочитайте Примечание по денормализации.

Вы можете реализовать денормализацию самостоятельно, используя mongoid события или использовать большой mongoid_denormalize gem. Это довольно прямо, и после его реализации вы можете использовать p.user_email или что-то в своих запросах.