I currently have the columns id, name, email, linkedin, company, contacted, recruiter, student and I want to add a new one called responded. I'm only finding answers on how to add new columns to all the existing instances in my db. So I did try this:
db.people.update({}, {$set: {"responded": false}}, false, true)
All my existing instances have a field :responded set to false by default. When I try to add a new person now I'm getting this error:
Mongoid::Errors::UnknownAttribute in PeopleController#create
message: Attempted to set a value for 'responded' which is not allowed on the model Person. summary: Without including Mongoid::Attributes::Dynamic in your model and the attribute does not already exist in the attributes hash, attempting to call Person#responded= for it is not allowed. This is also triggered by passing the attribute to any method that accepts an attributes hash, and is raised instead of getting a NoMethodError. resolution: You can include Mongoid::Attributes::Dynamic if you expect to be writing values for undefined fields often.
MongoDB does not have "columns", it does not have tables either. You have documents with fields.
I imagine you are using MongoID for your models, so you only need to define the field on your model
class Person
include Mongoid::Document
field :first_name, type: String
field :middle_name, type: String
field :last_name, type: String
field :responded, type: Boolean # something like this
end
https://docs.mongodb.com/mongoid/current/tutorials/mongoid-documents/#fields
Related
I have a mongodb database with a single collection containing 400+ entries of basic data.
I'm using Rails and the mongoid gem to link the two together however when I query my model in the rails console there are no entries found.
QuizQuestion.first
Yields no results
My model:
class QuizQuestion
include Mongoid::Document
field :question, type: String
field :correctAnswer, type: String
field :wrongAnswers, type: Array, default: []
field :category, type: String
end
I have configured the mongoid.yml configuration file to point to the address of the database.
Does anyone know how to correctly do this or where I'm going wrong?
The reasons why you see no result:
1) database config is incorrect and you are pointing to a different database on the same mongodb instance
2) class name does not match the name for the collection within mongo. Open up a console/terminal and type:
mongo
then type this:
show dbs
This is the name of the dbs you need in the first part
use x
Where x is the db name
show collections
This will list the names of the collections.
Once you have the name of your collections, you can add this to your model:
store_in collection: "name_of_collection_as_in_mongo"
Therefore if the name of your collection was quiz_question as shown in the mongo client you can do this on your model:
class QuizQuestion
include Mongoid::Document
store_in collection: "quiz_question"
field :question, type: String
field :correctAnswer, type: String
field :wrongAnswers, type: Array, default: []
field :category, type: String
end
The reason you are not seeing any records (if you are pointing at the correct db name) is most likely due to mongoid expecting the class name to equal a pluralised collection name so QuizQuestions == quiz_questions within mongo
Here's my use case:
I've got a collection full of sales tax rates that have been imported from CSV files. I created the Mongoid model to mirror the field names (these are not changeable):
class SalesTaxRate
include Mongoid::Document
field :state, type: String
field :zip_code, type: String
field :tax_region_name, type: String
field :tax_region_code, type: String
field :combined_rate, type: Float
end
Next, I'm building a model for use in my app. Let's say I want to create something called a Location:
class Location
include Mongoid::Document
field :name, type: String
field :street, type: String
field :city, type: String
field :state, type: String
field :zip_code, type: String
end
I'd like to be able to get a location's sales tax rate simply by calling something like this:
home = new Location(...)
home.sales_tax_rate
I'll never be setting the rate via home, just looking it up.
What's the "right" way to do this? I can think of two approaches -- the simple way seems to be just to define a method that does the lookup, as so:
class Location
...
def sales_tax_rate
SalesTaxRate.where(zip_code: self.zip_code).first.combined_rate
end
And this works. But I'm wondering whether I should be using a belongs_to association and, if so, why and how best to do that.
Still learning the ropes here, so apologies if this is a novice/silly question. Many thanks in advance!
If you have an index on zip_code in model SalesTaxRate what you are doing is essentially the same as what belongs_to will do. Just have a nil check in your code to ensure that it doesn't fail:
SalesTaxRate.where(zip_code: self.zip_code).first.try(:combined_rate)
# or
rate = SalesTaxRate.where(zip_code: self.zip_code).first
rate.nil? ? nil : rate.combined_rate
If you still want to go belongs_to route, you can define zip_code to be the identity in your SalesTaxRate. But you should take care of few things if you do that: First, all the zip codes in imported data need to be unique. Second, your location model can not have any zip code which is not available in SalesTaxRate otherwise you will face issues.
I have the following (using mongoid):
class FacebookUser
include Mongoid::Document
include Mongoid::Timestamps
field :uid, type: String
field :friends, type: Array
end
I am using mongoid and am wondering whether to store facebook_ids and facebook_ids_of_friends(Array) as BigDecimal, Integer or String. I will be using the uid for queries so am somewhat concerned about speed.
OR:
class FacebookUser
include Mongoid::Document
include Mongoid::Timestamps
field :uid, type: Integer
field :friends, type: Array #???How do I get this to store ints instead of strings
end
To avoid casting things repeatedly, I believe that the first option is better but wanted to get another opinion? In addition, how would I store an Array with Integer if I go with option 2?
Use a string. The only reason to use numeric types is if you will be doing calculations on the data. It is nonsensical to try to add two user id's so they should not be stored as integers.
Try this
class FacebookUser
identity :type => String
end
due to line identity :type => String your id of model will become String type and you can save facebook user id(uid) directly in there instead of creating a new field. The queries like finding users will be really easy and fast
For e.g.
find one user
FacebookUser.find(facebook user id)
This is my 2nd day playing with Ruby on Rails, so please be gentle :)
I have a very (hopefully) simple question: I want to set a publish date on my model, when it is indeed being created. I am using Mongoid, and it looks like this:
class Page
include Mongoid::Document
field :content, type: String
field :title, type: String
field :published_on, type: DateTime
end
Here is the question: should I set the published_on field from the create action, just before the call to #page.save? Or is there a better, more idiomatic way?
If I do it like that, meaning, calling #page.published_on = Date.now from within the controller's action, I get a warning:
Cannot find 'published_on=' for type 'Page'
If you put
class Page
include Mongoid::Document
include Mongoid::Timestamps
you get the rails automagic fields created_at and updated_at
So, I am having some issues with user authentication in embedded documents. I have two documents, one embedded in the other. A business has many members. The models look like this:
class Member
include Mongoid::Document
field :username, type: String
field :password, type: String
embedded_in :business
validates :username, :presence => true, :uniqueness => true, :length => 5..60
end
class Business
include Mongoid::Document
field :name, type: String
embeds_many :members
end
The problem is that it isn't validating the username's uniqueness in each model. When I save a member within a business, I can save a thousand of the same name. This of course is not going to work for a good authentication system. I am using Mongoid 2, Rails 3, and Ruby 1.9
This is a normal behavior when using embedded documents as explained here: MongoID validation
validates_uniqueness_of
Validate that the field is unique in the database: Note that for
embedded documents, this will only check that the field is unique
within the context of the parent document, not the entire database.
I think you want to try to create an Index in the username field that would ensure uniqueness among all the objects of that collection. Something like this:
ensureIndex({username:1},{unique:true});
EDIT: If you want Mongo to throw exception if a document with the same index value exists, you must avoid Mongo to do the “fire and forget” pattern. This means that the database will not wait for a response when you perform an update/write operation on a document.
And you want to pass this parameter: safe:true. By doing so Mongo should raise an exception if for any reason the document can't be inserted.