I am trying to match documents with Mongoid/Mongodb where array fields are used in the query. I've been struggling with $elemMatch
but can't seem to get it.
Project
can have admin
, member
, reader
usersProject
(HABTM)admin
admin
or member
Given a Project
document from 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 matches current_user.id
across either admin_ids
and member_ids
as long as there was only a single value in either of the arrays. As per the code above:
'123'
gives correct result'456'
gives no result (incorrect)Based on researching, I think I should be using $elemMatch
but am missing something.
As per the Project
document 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
The $elemMatch operator matches documents that contain an array field with at least one element that matches all the specified query criteria. If you specify only a single <query> condition in the $elemMatch expression, and are not using the $not or $ne operators inside of $elemMatch , $elemMatch can be omitted.
To search the array of object in MongoDB, you can use $elemMatch operator. This operator allows us to search for more than one component from an array object.
You can just simply use count method.
The $pull operator removes from an existing array all instances of a value or values that match a specified condition. The $pull operator has the form: { $pull: { <field1>: <value|condition>, <field2>: <value|condition>, ... } } To specify a <field> in an embedded document or in an array, use dot notation.
You need to get rid of the array while querying.
@projects = Project.any_of({:admin_ids => current_user.id},
{:member_ids => current_user.id}).entries
That should work.
I think you should just be able to use $in
rather than $elemMatch - as the mongodocs say:
"You only need to use [
$elemMatch
] when more than one field must be matched in the array element."
Have you tried something like the following?
Project.any_in(:member_ids => [ member_id_one, member_id_two ])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With