Как сопоставить mongoid документы, используя поля массива в запросе? - PullRequest
4 голосов
/ 22 февраля 2012

Я пытаюсь сопоставить документы с Mongoid / Mongodb, где поля массива используются в запросе.Я боролся с $elemMatch, но не могу его получить.

Контекст

  • A Project может иметь admin, member, reader users
  • На этих пользователей ссылается Project (HABTM)
  • Я хочу найти проекты, в которых:
    • Пользователь A равен admin
    • Пользователь B - admin или member
    • .. и т. Д.

Пример

Учитывая Project документ из консоли Rails:

[#<Project _id: 4f44355a9f5b7f385a000003, 
  _type: nil, name: "Project ABC", 
  desc: "some description", 
  admin_ids: 
    [BSON::ObjectId('123')], 
  member_ids: 
    [BSON::ObjectId('456'),
    BSON::ObjectId('789')], 
  reader_ids: []
>]

У меня был следующий код:

@projects = Project.any_of({:admin_ids => [current_user.id]}, 
                           {:member_ids => [current_user.id]}).entries

, который соответствует current_user.id для admin_ids и member_ids .так как было только одно значение в любом из массивов.Согласно приведенному выше коду:

  • Попытка сопоставить пользователя '123' дает правильный результат
  • Попытка сопоставить пользователя '456' не дает результата (неверный)

$ elemMatch

Основываясь на исследованиях, я думаю, что я должен использовать $elemMatch, но мне чего-то не хватает.

Согласно приведенному выше коду документа Project:

// test case: this works with array of one
Project.all(conditions: {:admin_ids => "123"}).entries

// failure case: empty result   
Project.all(conditions: {:member_ids => {'$elemMatch' => {:id => '456' } }}).entries

// failure case: empty result
Project.all(conditions: {:member_ids => {'$elemMatch' => {:id => BSON::ObjectId('4f44a4019f5b7f3d5200000d') } }}).entries

Ответы [ 2 ]

10 голосов
/ 22 февраля 2012

Вам нужно избавиться от массива во время запроса.

@projects = Project.any_of({:admin_ids => current_user.id}, 
                       {:member_ids => current_user.id}).entries

Это должно работать.

9 голосов
/ 22 февраля 2012

Я думаю, вы должны просто иметь возможность использовать $in вместо $ elemMatch - как mongodocs говорят:

"Вам нужно использовать только [$elemMatch], если в элементе массива должно быть найдено несколько полей. "

Вы пробовали что-то вроде следующего?

Project.any_in(:member_ids =>  [ member_id_one, member_id_two ])
...