2015-06-19 3 views
0

Я хочу, чтобы все дети имена, которые женского в коллекции в MongoDB используя ruby:Фильтрующие элементы в MongoDB коллекции с рубином

элементы в коллекции, как это:

[ 
{ "name" => "John", 
    "children" => [{"genre" => "male", "name" => "Rick"}, 
        {"genre" => "female", "name" => "Mary"} 
       ] 
}, 
{ "name" => "Richard", 
    "children" => [{"genre" => "female", "name" => "Vicky"}, 
        {"genre" => "female", "name" => "Mary"} 
       ] 
}] 

Когда я выполняю:

collection.find({"children" => {"genre" => "female"}}) 

Я получаю Mongo::OperationTimeout: Timed out waiting on socket read.

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

Если я использую чистый рубин, я мог бы сделать это с помощью:

collection.find({}).map { |d| 
    d["doc"]["children"].select { |rh| 
     rh["genre"] == "female" 
    }.map { |r| 
     r["name"] 
    } 
}.flatten.uniq 

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

+0

Вы должны actuall попытаться определить [именованные группы] (http://mongoid.org/en/mongoid/docs/querying. html # scoping) в ваших моделях. –

+0

Я не использую мангоид. Я использую 'mongo' gem для непосредственного подключения к mongodb –

ответ

-1

Если запрос займет много времени, вы можете попытаться изменить соединение с таймером сокета на драйвере mongo и https: //github.com/mongodb/mongo-ruby-driver/blob/master/lib/mongo/socket /tcp.rb и параметр тайм-аута запроса манги http://docs.mongodb.org/manual/reference/method/cursor.addOption/, или попробуйте использовать параметры пропуска() и ограничения для запроса.

0

Я ничего не могу о сокетов тайм-аут вы получили сказать, но этот запрос:

collection.find({"children" => {"genre" => "female"}}) 

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

collection.find("children.genre" => "female") 

Но он по-прежнему находит всех родителей, имеющих хотя бы одного ребенка-девочку. Мужские дети этих родителей также включены в эту точку зрения, и вы должны отфильтровать их после получения результата.

В качестве альтернативы, вы можете сделать весь выбор с помощью агрегата():

collection.aggregate([ 
    {:$unwind => '$children'}, 
    {:$match => {'children.genre' => 'female'}}, 
    {:$group => {_id: '$children'}} 
]).map { |c| c[:_id] } 
Смежные вопросы