6

I have the following code that works as expected:

Mongoid::Criteria.new(Question).where(:related_question_ids.size => 0)

However, I would like to perform the query to return questions with related_questions array greater than 0. For example,

Mongoid::Criteria.new(Question).where(:related_question_ids.size.gte => 0)

Is there a way to do this with mongoid or mongodb?

3 Answers 3

4

This query search if exists any object in the related_question_ids[0] field

Using js shell

db.questions.find("related_question_ids.0": {exists => true} )

Using mongoid

Mongoid::Criteria.new(Question).where(:"related_question_ids.0".exists => true)

You can search greater any size

Mongoid::Criteria.new(Question).where(:"related_question_ids.3".exists =>true)

This solve your problem

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

1 Comment

:some_relation_ids.exists => true would match the empty array []. I found the :some_relation_ids.nin => [nil, []] solution to work best to retrieve "present" (non-empty) items. It is very ugly, but a prettier solution would be a $empty/$present operator added to Mongoid, or something similar.
3

Another way to do this is to use the .nin (Not IN) form of the query:

Mongoid::Criteria.new(Question).where(:related_question_ids.nin => [nil,[]])

This will only return a Question where the related_question_ids is no nil and not an empty array.

Conversely, you can define :related_question_ids to have a default value (:default => []) and then you only need to query for .ne (Not Equal), like so:

Mongoid::Criteria.new(Question).where(:related_question_ids.ne => [])

Either should work.

1 Comment

I found this solution to be better, and it's written in Mongoid not just mongo syntax.
2

You can use the $size operator to query by array sizes. Consider the following example using the JS shell:

> db.foo.drop()
> db.foo.insert({_id: 1, x:[1,2]});
> db.foo.insert({_id: 2, x:[]});
> db.foo.insert({_id: 3, x:3});

> db.foo.find({x: {$size: 0}})
{ "_id" : 2, "x" : [ ] }

> db.foo.find({x: {$size: 1}})

> db.foo.find({x: {$size: 2}})
{ "_id" : 1, "x" : [ 1, 2 ] }

> db.foo.find({x: {$not: {$size: 2}}})
{ "_id" : 2, "x" : [ ] }
{ "_id" : 3, "x" : 3 }

> db.foo.find({x: {$not: {$size: 0}}})
{ "_id" : 1, "x" : [ 1, 2 ] }
{ "_id" : 3, "x" : 3 }

I'm not familiar with Mongoid, but I found an example using $size in this documentation.

Two caveats with $size are that it cannot utilize an index (other parts of the query certainly can) and it cannot be used in range queries. If you don't mind the additional bookkeeping, a viable option is to store the array's size in a separate field (likely indexed) and query on that any way you like.

2 Comments

This definitely works, and the correct way in mongoid would be: Question.where(:related_question_ids.not => {"$size"=>0}).size
Kamilski81 has the actual answer to this question about Mongoid.

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.