How to quickly query multiple collections in Mongoid? - ruby

Foo, Bar and Baz are all Mongoid collection models. There are the only collections in the DB.
Is there a more efficient way to get all the data in the DB?
Foo.all + Bar.all + Baz.all

I don't know a way of querying several collections at the time, and I believe that if one try to do that will defeat the purpose of using a NONSQL DB like MongoDB.
However, there is one way of archiving this behaviour in MongoDB. Using embedded documents. For example:
class Everything
include Mongoid::Document
include Mongoid::Timestamps
embeds_many :foos, class_name: 'Foo', inverse_of: :everything
embeds_many :bars, class_name: 'Bar', inverse_of: :everything
embeds_many :bazs, class_name: 'Bazs', inverse_of: :everything
end
class Foo
include Mongoid::Document
field :foo, type: String
embedded_in :everything, class_name: 'Everything', inverse_of: :foos
end
class Bar
include Mongoid::Document
field :bar, type: String
embedded_in :everything, class_name: 'Everything', inverse_of: :bars
end
class Bazs
include Mongoid::Document
field :baz, type: String
embedded_in :everything, class_name: 'Everything', inverse_of: :bazs
end
Doing Everything.all will retrieve all documents in Everything along with all the embedded documents in one call.

Related

Referencing two of the same document from another document in Mongoid

I am trying to store messages and I want to store to and from User reference as below:
class Message
include Mongoid::Document
include Mongoid::Timestamps
field :from, type: Moped::BSON::ObjectId
field :to, type: Moped::BSON::ObjectId
end
class User
include Mongoid::Document
field :username, type: String
end
Is the above the correct way of doing so? I can imagine one way is to create User as a custom type, but that seems a lengthy direction to take. Ideally I want to be able to reference the User directly as so: message.from.username or message.from['username'] and be able to validate the presence of the from and to fields.
Any help would be much appreciated.
class Message
belongs_to :from, class_name: 'User', inverse_of: nil
belongs_to :to, class_name: 'User', inverse_of: nil
...
Message.where(from: my_user)

Mongoid validates_presence_of a belongs_to item

How do I go about validating the presence of an item defined as belongs_to? In other words:
class Temp
include Mongoid::Document
include Mongoid::Timestamps
belongs_to :user
end
and I wish to make sure a user was input.
Thanks in advance!
From the fine manual:
The parent document of the relation should use the has_many macro to indicate is has n number of referenced children, where the document that is referenced uses belongs_to.
class Band
include Mongoid::Document
has_many :members
end
class Member
include Mongoid::Document
field :name, type: String
belongs_to :band
end
[...]
# The parent band document.
{ "_id" : ObjectId("4d3ed089fb60ab534684b7e9") }
# The child member document.
{
"_id" : ObjectId("4d3ed089fb60ab534684b7f1"),
"band_id" : ObjectId("4d3ed089fb60ab534684b7e9")
}
Take note of the band_id that represents the belongs_to :band relationship. So saying:
belongs_to :user
implicitly adds a field :user_id to your Temp. That means that you can simply:
validates_presence_of :user_id
to make sure that a :user_id has been given. If you want to ensure that the :user_id is valid then you could:
validates_presence_of :user
and the validation will make sure that temp.user (i.e. User.find(temp.user_id)) finds something.

Mongoid has_and_belongs_to_many, inverse_of: :nil, store_as

In my code I have a user class:
class User
include Mongoid::Document
has_and_belongs_to_many :person_record_bookmarks, inverse_of: nil, :class_name => "PersonRecord"
end
now it will generate person_record_bookmarks_ids in my document. This name is too long, is there any way to store it as shorter name in the database? In embed documents we can use store_as:, but seems it doesn't work for references.
foreign_key is what you are looking for
class User
include Mongoid::Document
has_and_belongs_to_many :person_record_bookmarks, inverse_of: nil, :class_name => "PersonRecord", foreign_key :shorter_name
end
then your user will be:
{...shorter_name:[ObjectId("..."),ObjectId("...")]...}
You can user user.shorter_name to retrieve the list of ids or user.person_record_bookmarks to retrieve all PersonRecordBookmarks.where({_id: {$in: shorter_name})

Mondoid search one document with multiples in a has_many/belongs_to relationship

I have this releationship
class Cupboard
include Mongoid::Document
field :name, type: String
has_many :ingredients
end
class Recipe
include Mongoid::Document
field :name, type: String
has_many :ingredients
end
class Ingredient
include Mongoid::Document
field :name, type: String
field :description, type: String
belongs_to :cupboard
belongs_to :recipe
end
I need to create a method in Cupboard model to find a recipe that contains the same ingredients as the cupboard, I don't find in the Mongoid docs a method to find it.
I need something like Recipe.find( #all cupboard.ingredients.ids )
thanks in advance
def shared_recipes
ingredients.map(&:recipe).uniq
end

Mongoid: blank belongs_to association

I have belongs_to :provider in my model, and provider_id is set, but association is still blank:
irb(main):095:0> o2.provider_id
=> BSON::ObjectId('4e0472f36d40ec0004000001')
irb(main):096:0> o2.provider
=> nil
Also, model has provider_id= method with "write_attribute(:provider_id, provider_id)" inside.
What could be wrong here?
Mongoid version is 2.4.0
Thank you!
I believe you need a has_one or has_many association in your other model.
class Foo
include Mongoid::Document
belongs_to :bar
end
class Bar
include Mongoid::Document
has_one :foo
end

Resources