How to match mongoid documents using array fields in a request?

I am trying to map documents to Mongoid / Mongodb, where the request uses array fields. I struggled with $elemMatch but didn't seem to be able to get it.

Context

  • A Project may have admin , member , reader users
  • These users link to Project (HABTM)
  • I want to find projects where:
    • User A admin
    • User B admin or member
    • .. etc.

Example

A Project document is provided from the Rails console:

 [#<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: [] >] 

I had the following code:

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

Which corresponds to current_user.id for all admin_ids and member_ids , if there was only one value in any of the arrays. According to the code above:

  • Attempting to match user '123' gives correct result
  • Attempting to map user '456' does not produce result (incorrect)

$ elemMatch

Based on the research, I think I should use $elemMatch , but something is missing.

According to the Project code above:

 // 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 
+4
source share
2 answers

You need to get rid of the array during the request.

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

That should work.

+10
source

I think you should just use $in , not $ elemMatch, as mongodocs say:

"You need to use [ $elemMatch ] when you need to map multiple fields to an array element."

Have you tried something like the following?

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

Source: https://habr.com/ru/post/1397763/


All Articles