27

The solution for this question might look pretty simple, but I've been waving around with no answer.

I'm using Mongoid in my Rails 4.1.4 app. I have a model which contains an Array field that will house String values.

I need a Mongoid's scope in the model to retrieve those instances where this Array field contains a specific String value, given as a parameter to the scope. Let's say we have this model:

class SomeModel
  include Mongoid::Document
  include Mongoid::Timestamps

  field :some_array, type: Array, default: Array.new

  scope :some_scope, ->(value){ elem_match(some_array: value) }

end

The above scope doesn't work because, obviously, in MongoDB $elemMatch needs to receive a Criteria as the value. But, how would be the Criteria to just say that the element has to be equal to the given value???.

Any clues on how to write this pretty simple scope???.

Regards!!!. Thanks in advance.

1 Answer 1

44

You're drastically overcomplicated things. If a field holds an array then you can search it as though it wasn't an array. For example, if you have this in a document:

{ some_array: [ 'where', 'is', 'pancakes', 'house?' ] }

and you do a query like this:

where(:some_array => 'pancakes')

you'll find that document. You don't need $elemMatch or anything complicated here; you can pretend that the array is a single value for simple queries like you have:

scope :some_scope, ->(value) { where(:some_array => value) }

You only need to get into $elemMatch if you want to apply multiple conditions to each element of the array, things like this from the $elemMatch docs:

   results: { $elemMatch: { $gte: 80, $lt: 85 } }
// ^^^^^^^array           ^^^^^^^^^^^^^^^^^^^^^multiple conditions

Don't feel bad, the current MongoDB docs aren't exactly clear on this stuff (or at least I can't find an explicit explanation).

Sign up to request clarification or add additional context in comments.

1 Comment

Didn't come to my thoughts that it could be that simple. Let me give it a try and I'll let you know if it indeed worked for me. Thanks!.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.