У меня есть ситуация, когда мне нужно вернуть одну коллекцию объектов из монго, но для получения результатов нужно использовать два запроса. Порядок этих результатов важен, потому что они разбиты на страницы.
Вот первый запрос: (объявления на основе категории и ценового диапазона)
my_listings = MoListing.where(criteria_a)
Второй запрос должен использовать результаты первого запроса в качестве фильтра. Итак, что-то вроде:
everything_else = MoListing.where(criteria_b)
Затем объедините результаты:
my_listings << everything_else
И, наконец, верните результаты с разбивкой на страницы:
my_listings.page(1).per(25)
Кажется, часть моей проблемы заключается в том, что запросы монго не выполняются до тех пор, пока они не потребуются. Есть ли способ запустить выполнение запроса в заданной точке? Или есть другой подход, который я должен использовать при создании этого набора результатов?
Обновить с дополнительной информацией
Поведение, которое я вижу, заключается в том, что возвращаются только результаты в listings
. Я также подтвердил, что everything_else
действительно содержит ожидаемые записи (48 записей в my_listings, 52 во всем_остальном, как и ожидалось).
При применении .all
к моим запросам, как указано в комментариях, это не влияет. puts listings.inspect
приводит к
10:57:00 web.1 | #<Mongoid::Criteria
10:57:00 web.1 | selector: {"price"=>{"$gte"=>25, "$lte"=>75}},
10:57:00 web.1 | options: {},
10:57:00 web.1 | class: MoListing,
10:57:00 web.1 | embedded: false>
Однако listings.count
приводит к 48
. Я просто пропустил какой-то глупый простой способ слияния этих результатов? И как только я получу результаты в одной коллекции, как это повлияет на последующие функции разбиения на страницы. Я использую kaminari
для нумерации страниц.
Обновление 2
Согласно ответу ниже и моим собственным пробам и ошибкам, я нашел to_a решением, но не идеальным. Это работает:
#merge the results together as an Array
results = (listings.to_a | everything_else.to_a)
Это приводит к тому, что нумерация страниц через Kaminari должна измениться, поскольку мы больше не работаем с критериями монго, а вместо этого используем стандартный массив. Вот новый метод пагинации:
Kaminari.paginate_array(results).page(page).per(per_page)
Работа с небольшим набором данных из 100 записей, это нормально и денди - 54 мс
"debug":{"success":true,"pre_render_duration":54.808775999999995,"overall_duration":86.36554100000001,"count":25},"pagination":{"total_pages":4,"current_page":1}}
Однако, используя больший набор данных, я вижу значительно более медленное время при использовании метода .to_a для их объединения. Хотя примеры не совсем похожи друг на друга, эта большая разница указывает на проблему, заключающуюся в том, что to_a возвращает все, что вынуждает Каминари работать с гораздо большим количеством реальных данных:
Мои результаты без to_a, просто возвращая все записи с примененными критериями - 15 мс
"debug":{"success":true,"pre_render_duration":15.107164,"overall_duration":18.267599,"count":25},"pagination":{"total_pages":81,"current_page":1}}
Мои результаты с to_a, объединение двух наборов результатов - 415 мс
"debug":{"success":true,"pre_render_duration":415.258199,"overall_duration":450.66537800000003,"count":25},"pagination":{"total_pages":81,"current_page":1}}
Подводя итог, это недопустимый вариант. Возврат каждого набора данных по отдельности занимает ‹15 мс даже с большим набором данных, поэтому я думаю, что мне нужно выполнить способ объединения критериев вместе, чтобы один запрос выполнялся для Mongo, позволяя выполнять разбиение на страницы в БД, где это должно быть быть.
В SQL я бы сделал что-то вроде
select
*
from
listings
where
field = "blah"
union all
select
*
from
listings
where
field <> "blah"
Возможно ли это сделать в Монго?
.all
после ваших запросов и они будут выполняться там сами и ленивой загрузки не будет. - person Jatin Ganhotra   schedule 07.09.2012