2012-05-22 6 views
0

У меня есть коллекция Mongo, которая просто ссылается на ID на другую коллекцию. Гипотетически коллекция, которую я конкретно имею в виду, можно назвать:Монтойский запрос, ссылающийся на идентификатор, но не содержащий встроенный документ

Прогулки. У Walks есть ссылка на owner_id. Владелец берет много прогулок с его многочисленными домашними животными каждый день. Я хочу сделать запрос «Прогулки» для списка N owner_ids и получить только последнюю прогулку, которую они сделали для каждого владельца и группы, которые принадлежат owner_id. Чтобы получить список всех прогулок по указанному списку, мы бы сделали что-то вроде этого.

Walk.any_in(:owner_id => list_of_ids)

Мой вопрос, есть ли способ запроса, который LIST_OF_IDS, получить только один прогулку за owner_id (последний они взяли, который может быть отсортирован по полю created_at и возвращенное в хэш, где каждая прогулка это указывает на owner_id, такие как:.

{ 5 => {..walk data..}, 10 => {.. walk data ..}}

ответ

0

Вот ответ, который использует команду группы MongoDB в для целей тестирования я использовал walk_time я nstead of created_at. Надеюсь, что это поможет и вам понравится.

class Owner 
    include Mongoid::Document 
    field :name, type: String 
    has_many :walks 
end 

class Walk 
    include Mongoid::Document 
    field :pet_name, type: String 
    field :walk_time, type: Time 
    belongs_to :owner 
end 

тест/блок/walk_test.rb

require 'test_helper' 

class WalkTest < ActiveSupport::TestCase 
    def setup 
    Owner.delete_all 
    Walk.delete_all 
    end 

    test "group in Ruby" do 
    walks_input = { 
     'George' => [ ['Fido', 2.days.ago], ['Fifi', 1.day.ago], ['Fozzy', 3.days.ago] ], 
     'Helen' => [ ['Gerty', 4.days.ago], ['Gilly', 2.days.ago], ['Garfield', 3.days.ago] ], 
     'Ivan' => [ ['Happy', 2.days.ago], ['Harry', 6.days.ago], ['Hipster', 4.days.ago] ] 
    } 
    owners = walks_input.map do |owner_name, pet_walks| 
     owner = Owner.create(name: owner_name) 
     pet_walks.each do |pet_name, time| 
     owner.walks << Walk.create(pet_name: pet_name, walk_time: time) 
     end 
     owner 
    end 
    assert_equal(3, Owner.count) 
    assert_equal(9, Walk.count) 
    condition = { owner_id: { '$in' => owners[0..1].map(&:id) } } # don't use all owners for testing 
    reduce = <<-EOS 
     function(doc, out) { 
     if (out.last_walk == undefined || out.last_walk.walk_time < doc.walk_time) 
      out.last_walk = doc; 
     } 
    EOS 
    last_walk_via_group = Walk.collection.group(key: :owner_id, cond: condition, initial: {}, reduce: reduce) 
    p last_walk_via_group.collect{|r|[Owner.find(r['owner_id']).name, r['last_walk']['pet_name']]} 
    last_walk = last_walk_via_group.collect{|r|Walk.new(r['last_walk'])} 
    p last_walk 
    end 
end 

тест выход

Run options: --name=test_group_in_Ruby 

# Running tests: 

[["George", "Fifi"], ["Helen", "Gilly"]] 
[#<Walk _id: 4fbfa7a97f11ba53b3000003, _type: nil, pet_name: "Fifi", walk_time: 2012-05-24 15:39:21 UTC, owner_id: BSON::ObjectId('4fbfa7a97f11ba53b3000001')>, #<Walk _id: 4fbfa7a97f11ba53b3000007, _type: nil, pet_name: "Gilly", walk_time: 2012-05-23 15:39:21 UTC, owner_id: BSON::ObjectId('4fbfa7a97f11ba53b3000005')>] 
. 

Finished tests in 0.051868s, 19.2797 tests/s, 38.5594 assertions/s. 

1 tests, 2 assertions, 0 failures, 0 errors, 0 skips 
Смежные вопросы