2016-07-24 3 views
0

У меня есть модели, как этотRails - Mongoid запрашивающий на поле ассоциации

class TestOne 
    field value 

    belongs_to test_two ,:class_name => 'TestTwo' 
end 

class TestTwo 
    field name 
    field start_time, :type => DateTime 

    has_many TestOne 

end 

I am running a query of range like this 

result = TestOne.where(:value => "some_value" , 'test_two.start_time' => (Time.now-1.days..Time.now + 1.days).last 

В результате набор выше запроса пуст, даже если существует несколько записи в TestOne, которые удовлетворяют критерии. Может ли кто-нибудь предположить, что я могу делать неправильно.

ответ

2

Запрос MongoDB может иметь доступ только к одной коллекции за раз, здесь нет объединений.

Когда вы говорите:

'test_two.start_time' => (...) 

MongoDB будет искать поле в test_ones имени test_two, который является хэш (или массив хешей) с start_time поля внутри этой хэш. У вас нет такой структуры, чтобы ваш запрос ничего не нашел.

Кроме того, вы можете запросить любую коллекцию MongoDB для любых полей, которые вам нравятся, и MongoDB не будет жаловаться; документы внутри коллекции не имеют установленной для каждой коллекции структуры: любой документ в любой коллекции может содержать любые поля с любыми типами. Вот почему вы можете использовать этот запрос, не жалуясь никому.

Вам нужно сделать запрос в два этапа (т.е. сделать объединение вручную):

test_two_ids = TestTwo.where(:start_time => (Time.now-1.days..Time.now + 1.days)).pluck(:id) 
result = TestOne.where(:value => "some_value" , :test_two_id.in => test_two_ids).last 

Есть несколько альтернатив, которые больше работы:

  1. Держите копию db.test_twos.start_time в коллекции db.test_ones (т.е. прекомпретировать СОЕДИНЕНИЕ путем денормализации). Это потребовало бы, чтобы вы обновляли копии каждый раз, когда изменялись db.test_twos.start_time, и вам нужно периодически проверять все копии и исправлять сломанные, потому что они перестают синхронизироваться.
  2. Если вам не нужен TestTwo, то для его самостоятельного использования тогда вставьте TestTwo внутри TestOne. Это оставило бы вас с хэш-полем test_two внутри вашей коллекции db.test_ones, и ваш исходный запрос будет работать. Тем не менее, вы больше не сможете получить доступ к TestTwo, вам придется пройти через TestOne.
+1

использовать 'pluck (: id)' вместо '.only (: id) .map (&: id)' –

+0

@ CyrilDuchon-Doris. Вы правы, 'pluck' здесь лучше. –

Смежные вопросы